/*
 * TraceabilityTreeView.java
 *
 * $Id: TraceabilityTreeView.java,v 1.5 2009-09-28 10:18:46 mario Exp $
 */
package org.ceteca.explica.client.traceability.gui;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.StringTokenizer;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.Bullet;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.graphics.GlyphMetrics;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.swt.widgets.Widget;
import org.xnap.commons.i18n.I18n;
import org.xnap.commons.i18n.I18nFactory;

import org.ceteca.explica.client.ClientContext;
import org.ceteca.explica.core.traceability.InterfaceTraceabilityTree;

import org.ceteca.explica.client.gui.ExplicaGUIBuilder;
import org.ceteca.explica.client.traceability.gui.TraceabilityTreeItem;
import org.ceteca.explica.client.traceability.gui.TraceabilityTreeView;
import org.ceteca.javaglade.GenericListener;
import org.ceteca.javaglade.Gui;
import org.ceteca.javaglade.InterfaceGladeGtk;
import org.ceteca.javaglade.InterfaceGladeParser;
import org.ceteca.javaglade.JavaGlade;
import org.ceteca.javaglade.JavaGladeException;
import org.ceteca.javaglade.JavaGladeUtil;
import org.ceteca.javaglade.Localizer;
import org.ceteca.javaglade.handlers.GenericHandler;
import org.ceteca.javaglade.toolkit.swt.StatusBar;
import org.ceteca.javaglade.toolkit.swt.SwtDialog;
import org.ceteca.javaglade.toolkit.swt.SwtToolkit;
import org.ceteca.javaglade.toolkit.swt.SwtTopLevelWindow;
import org.ceteca.javaglade.toolkit.swt.SwtWidget;
import org.ceteca.explica.core.traceability.tree.bl.TraceabilityTreeBLL;
import org.ceteca.explica.core.traceability.tree.ProcessInfo;
import org.ceteca.explica.core.traceability.tree.ProductInfo;
import org.ceteca.explica.core.traceability.tree.PropertyInfo;
import org.ceteca.explica.core.traceability.tree.PurchaseInfo;
import org.ceteca.explica.core.traceability.tree.TraceabilityTree;
import org.ceteca.explica.core.traceability.tree.WarehouseInfo;
import org.ceteca.explica.core.traceability.tree.WorkcenterInfo;
import org.ceteca.explica.core.traceability.tree.WorkerInfo;
import org.ceteca.explica.core.traceability.tree.parser.TraceabilityTreeParser;
import org.ceteca.explica.core.util.BarcodeGenerator;
import org.ceteca.explica.core.util.DateTime;
import org.ceteca.explica.core.util.Validator;
import org.ceteca.explica.core.util.LoggerFactory;
import org.ceteca.explica.core.util.ResultMessage;

/**
 * Helper class that implements the Traceability Tree Viewer GUI. 
 * It completes the glade file specification to add extra features.
 * It also implements the event handlers for the Traceability Tree
 * Viewer screens and dialogs.
 * Manages the tree contents of the viewer, items, edition panels,
 * and management of traceability files.
 * <br/>
 * Responsibilities:
 * <ul>
 * 	<li>Definition and inicialization of the Traceability Tree Viewer
 * GUI. </li>
 *  <li>Management of traceability tree content (items of any kind,
 * traceability files ...).</li>
 *  <li>Traceability Tree Viewer event handling.</li>
 * </ul>
 * <br/>
 * @author Mario García García <mario@imagos.es>
 * Copyright (c) 2007 Fundación Centro Tecnolóxico da Carne
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * <br/>
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * <br/>
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
public class TraceabilityTreeView extends GenericHandler implements Localizer {
	/** Catalog of tree items (indexed by their corresponding widget) */
	private Hashtable<Widget, TraceabilityTreeItem> items;
	/** Catalog of tree items (indexed by their corresponding name) */
	private Hashtable<String, TraceabilityTreeItem> itemsByName;
	/** Flag that shows when the insert item mode is enabled */
	private boolean insertMode;
	/** Keeps the insert item type selected by the user */
	private int insertType;
	/** Keeps the traceability file path of the opened file */
	private String traceabilityFilename;
	/** Keeps the day widget when user presses a choose date button */
	private Text dayWidget;
	/** Keeps the month widget when user presses a choose date button */
	private Text monthWidget;
	/** Keeps the year widget when user presses a choose date button */
	private Text yearWidget;
	
	/** Unique instance of the TraceabilityTreeView class. Singleton pattern */
	private static TraceabilityTreeView instance;
	
	private Gui gui;

	/** Returns the unique instance of the TraceabilityTreeView class.
	 * Implements the singleton dessign pattern.
	 * @return TraceabilityTreeView, unique instance of TraceabilityTreeView.
	 */
	public static final TraceabilityTreeView getInstance() {
		if (instance == null)
			instance = new TraceabilityTreeView();
		return instance;
	}

	/**
	 * Private default constructor por TraceabilityTreeView objects.
	 */
	private TraceabilityTreeView() {
		System.out.println("Inicializando TraceabilityTreeView");
		this.items = new Hashtable<Widget, TraceabilityTreeItem>();
		this.itemsByName = new Hashtable<String, TraceabilityTreeItem>();
		this.gui = null;
				
		// Init the logging system for the TraceabilityTreeViewer module
		System.out.println(this.getClass().getResource("/org/ceteca/explica/core/traceability/log4j.xml").getPath());
		LoggerFactory.initLogger(null, this.getClass().getResourceAsStream("/org/ceteca/explica/core/traceability/log4j.xml"));
	}

	/**
	 * Initializes the Traceability Tree Viewer engine and builds
	 * the main window of the Viewer. Searches automatically for
	 * the glade interface file with the application GUI configuration.
	 */
	public void buildTreeView() {
		this.buildTreeView("traceabilitytreeviewer.glade");
	}
	
	/**
	 * Initializes the Traceability Tree Viewer engine and builds
	 * the main window of the Viewer.
	 * @param gladeFilename String, file path of the Traceability Tree
	 * Viewer glade file that defines the GUI.
	 */
	public void buildTreeView(String gladeFilename) {
		this.buildTreeView(gladeFilename, null, null);
	}
	
	/**
	 * Initializes the Traceability Tree Viewer engine and builds
	 * the main window of the Viewer.
	 * @param gladeFilename, name of the traceability tree viewer .glade file
	 * @param parentWidget SwtWidget, parent widget where the Traceability Tree
	 * Viewer will be embedded. Null in case a new window is opened.
	 * @param parentGui Gui, parent Gui where the Traceability tree viewer component
	 * will be embedded. Null in case a new window is opened.
	 */
	public void buildTreeView(String gladeFilename, SwtWidget parentWidget, Gui parentGui) {
		// Build the main window of the TraceabilityTreeViewer component
		try {
			if (parentWidget != null) {
				this.gui = JavaGladeUtil.getInstance().build(gladeFilename, "TraceabilityTree", parentGui, InterfaceTraceabilityTree.TREEVIEWER_PANEL_NAME, 
						parentWidget.getWidget(), parentWidget.getWidgetName(), null, SWT.COLOR_WIDGET_BACKGROUND);
				System.out.println("ACABO EL TRACEABILITY TREE VIEWER 11111111111111111111");
			}
			else {
				this.gui = JavaGladeUtil.getInstance().build(gladeFilename, "TraceabilityTree", SWT.COLOR_WIDGET_BACKGROUND);
				System.out.println("ACABO EL TRACEABILITY TREE VIEWER 22222222222222222222");
			}
		}
		catch (JavaGladeException jEx) {
			jEx.printStackTrace();
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
		
		// Get the root composite where the edition panels will be embedded
		Composite rootComposite = (Composite)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PANEL_NAME);
		
		// Build the stack layout to superimpose all the child edition panels
		final StackLayout layout = new StackLayout();
		rootComposite.setLayout(layout);
		
		// Build an empty panel to show as the default panel of the stack layout
		Widget w = JavaGladeUtil.getInstance().getSwtToolkit().emptyPanel(rootComposite, InterfaceTraceabilityTree.TREEVIEW_EDIT_EMPTY_PANEL_NAME);
		((Control)w).setLayoutData(null);
		this.gui.addWidget("panel_treeView_default", w, InterfaceTraceabilityTree.TREEVIEW_EDIT_PANEL_NAME);
		
		// Set the showed layout to none
		layout.topControl = (Control)w;
		
		// Build the product edition panel
		buildEditPanel(InterfaceTraceabilityTree.TREEVIEW_EDIT_PRODUCT_GUINAME, InterfaceTraceabilityTree.TREEVIEW_EDIT_PRODUCT_PANEL_NAME, 
				InterfaceTraceabilityTree.GLADE_PRODUCT_EDITION_FILENAME, 
				rootComposite);
		// Build the comment edition panel
		buildEditPanel(InterfaceTraceabilityTree.TREEVIEW_EDIT_COMMENT_GUINAME, 
				InterfaceTraceabilityTree.TREEVIEW_EDIT_COMMENT_PANEL_NAME, 
				InterfaceTraceabilityTree.GLADE_COMMENT_EDITION_FILENAME, 
				rootComposite);
		// Build the worker edition panel
		buildEditPanel(InterfaceTraceabilityTree.TREEVIEW_EDIT_WORKER_GUINAME, 
				InterfaceTraceabilityTree.TREEVIEW_EDIT_WORKER_PANEL_NAME, 
				InterfaceTraceabilityTree.GLADE_WORKER_EDITION_FILENAME, 
				rootComposite);
		// Build the workcenter edition panel
		buildEditPanel(InterfaceTraceabilityTree.TREEVIEW_EDIT_WORKCENTER_GUINAME, 
				InterfaceTraceabilityTree.TREEVIEW_EDIT_WORKCENTER_PANEL_NAME, 
				InterfaceTraceabilityTree.GLADE_WORKCENTER_EDITION_FILENAME, 
				rootComposite);
		// Build the warehouse edition panel
		buildEditPanel(InterfaceTraceabilityTree.TREEVIEW_EDIT_WAREHOUSE_GUINAME, 
				InterfaceTraceabilityTree.TREEVIEW_EDIT_WAREHOUSE_PANEL_NAME, 
				InterfaceTraceabilityTree.GLADE_WAREHOUSE_EDITION_FILENAME, 
				rootComposite);
		// Build the property edition panel
		buildEditPanel(InterfaceTraceabilityTree.TREEVIEW_EDIT_PROPERTY_GUINAME,
				InterfaceTraceabilityTree.TREEVIEW_EDIT_PROPERTY_PANEL_NAME, 
				InterfaceTraceabilityTree.GLADE_PROPERTY_EDITION_FILENAME, 
				rootComposite);
		// Fill the combo of property types
		fillPropertyTypeCombo();
		
		// Build the process edition panel
		buildEditPanel(InterfaceTraceabilityTree.TREEVIEW_EDIT_PROCESS_GUINAME,
				InterfaceTraceabilityTree.TREEVIEW_EDIT_PROCESS_PANEL_NAME, 
				InterfaceTraceabilityTree.GLADE_PROCESS_EDITION_FILENAME, 
				rootComposite);
		// Build the purchase edition panel
		buildEditPanel(InterfaceTraceabilityTree.TREEVIEW_EDIT_PURCHASE_GUINAME,
				InterfaceTraceabilityTree.TREEVIEW_EDIT_PURCHASE_PANEL_NAME, 
				InterfaceTraceabilityTree.GLADE_PURCHASE_EDITION_FILENAME, 
				rootComposite);
		// Build the appcc edition panel
		buildEditPanel(InterfaceTraceabilityTree.TREEVIEW_EDIT_APPCC_GUINAME,
				InterfaceTraceabilityTree.TREEVIEW_EDIT_APPCC_PANEL_NAME, 
				InterfaceTraceabilityTree.GLADE_APPCC_EDITION_FILENAME, 
				rootComposite);

		// Add a resized listener to capture the resize of edit panel events
		Composite editPanel = (Composite)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PANEL_NAME);
		editPanel.addListener(SWT.Resize, new GenericListener("on_editPanel_resized", this));
		
		Text textProdRef = (Text)this.getEditProductGui().getWidget("entryTrProductRef");
		textProdRef.addListener(SWT.FocusIn, new GenericListener("on_editPanel_resized", this));
		
		this.gui.printWidgets(LoggerFactory.getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY));

		// Disable the tree widget
		Tree tree = (Tree)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_WIDGET_NAME);
		tree.setEnabled(false);

		((Composite)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEWER_PANEL_NAME)).layout(true);
		
		
		// Build the select tree item type dialog GUI
		try {
			Gui itemTypeGui = ExplicaGUIBuilder.getInstance().buildGUI("treeViewer_selectTreeItemType", 
					InterfaceTraceabilityTree.TREEVIEWER_ITEMTYPE_GLADE_FILE, 
					this.gui,
					this.gui.getParentWindow());
			System.out.println(itemTypeGui.toString());
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
		// Build the date chooser dialog GUI
		try {
			Gui itemTypeGui = ExplicaGUIBuilder.getInstance().buildGUI("treeViewer_selectDate", 
					InterfaceTraceabilityTree.TREEVIEWER_DATECHOOSER_GLADE_FILE, 
					this.gui,
					this.gui.getParentWindow());
			System.out.println(itemTypeGui.toString());
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
		
		// Build the file chooser dialog GUI
		try {
			Gui itemTypeGui = ExplicaGUIBuilder.getInstance().buildGUI("treeViewer_selectFile", 
					InterfaceTraceabilityTree.TREEVIEWER_FILECHOOSER_GLADE_FILE, 
					this.gui,
					this.gui.getParentWindow());
			System.out.println(itemTypeGui.toString());
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}

		// Build the result message dialog GUI
		try {
//			if (parentGui != null) {
				Gui itemTypeGui = ExplicaGUIBuilder.getInstance().buildGUI("treeViewer_message", 
						InterfaceTraceabilityTree.TREEVIEWER_RESULTMESSAGE_GLADE_FILE, 
						this.gui,
						this.gui.getParentWindow());
				System.out.println(itemTypeGui.toString());
/*			}
			else {
				Gui itemTypeGui = ExplicaGUIBuilder.getInstance().buildGUI("treeViewer_message", 
						InterfaceTraceabilityTree.TREEVIEWER_RESULTMESSAGE_GLADE_FILE,
						this.gui, this.gui.getParentWindow());
				System.out.println(itemTypeGui.toString());
			}
*/
		}
		catch (Exception ex) {
			ex.printStackTrace();
		}
		
		if (parentGui == null)
			this.gui.eventLoop();
	}
	
	/**
	 * Builds the graphical traceability tree made of the traceability
	 * file.
	 * Build all the items defined in the traceability tree and show
	 * them to the user.
	 * @param traceabilityFilename String, path to the traceability file.
	 */
	public void openTraceabilityFile(String traceabilityFilename) {
		TraceabilityTree trTree = null;
		
		// Parse the traceability file
		try {
			TraceabilityTreeParser parser = new TraceabilityTreeParser(traceabilityFilename);
			trTree = parser.getTrTree();
		}
		catch (Exception tEx) {
			tEx.printStackTrace();
			trTree = null;
		}
		
		// Get the tree widget
		Tree t = (Tree)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_WIDGET_NAME);
		
		// Delete the previous traceability tree contents
		this.deleteTreeContents(t);
		
		// Build the traceability tree contents
		Widget parent = null;
		try {
			// Get the parent widget of the tree (the TreeView widget)
			parent = t;
			// Enable the tree widget
			((Tree)parent).setEnabled(true);

			
			// Build the traceability tree nodes
			if (trTree != null) {
				this.buildTreeContent(trTree, parent);
			}
			
			// Add a selection listener to capture the selection of tree items events
			parent.addListener(SWT.Selection, new GenericListener("on_item_selected", this));				
			
			LoggerFactory.getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY).
				debug(String.format(InterfaceTraceabilityTree.TREEVIEW_LOG_TREECONTENT, this.items));
			
			// Set the filename of the traceability file
			this.setTraceabilityFilename(traceabilityFilename);
		} // try
		catch (Exception ex) {
			ex.printStackTrace();
		} // try-catch
	}
	
	/**
	 * Builds the graphical traceability tree made of the traceability
	 * file.
	 * Build all the items defined in the traceability tree and show
	 * them to the user.
	 * @param trData byte[], traceability data of the product. It's the
	 * traceability bytes read from the traceability file.
	 */
	public void openTraceabilityFile(byte[] trData) {
		TraceabilityTree trTree = null;
		
		// Parse the traceability file
		try {
			TraceabilityTreeParser parser = new TraceabilityTreeParser(trData);
			trTree = parser.getTrTree();
		}
		catch (Exception tEx) {
			tEx.printStackTrace();
			trTree = null;
		}
		
		// Get the tree widget
		Tree t = (Tree)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_WIDGET_NAME);
		
		// Delete the previous traceability tree contents
		this.deleteTreeContents(t);
		
		// Show the empty edition panel
		this.showEmpty();
		
		// Build the traceability tree contents
		Widget parent = null;
		try {
			// Get the parent widget of the tree (the TreeView widget)
			parent = t;
			// Enable the tree widget
			((Tree)parent).setEnabled(true);

			
			// Build the traceability tree nodes
			if (trTree != null) {
				this.buildTreeContent(trTree, parent);
			}
			
			// Add a selection listener to capture the selection of tree items events
			parent.addListener(SWT.Selection, new GenericListener("on_item_selected", this));				
			
			LoggerFactory.getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY).
				debug(String.format(InterfaceTraceabilityTree.TREEVIEW_LOG_TREECONTENT, this.items));
			
			// Set the filename of the traceability file
			this.setTraceabilityFilename(null);
		} // try
		catch (Exception ex) {
			ex.printStackTrace();
		} // try-catch
	}
	
	/**
	 * Delete the graphical traceability tree made of the traceability
	 * file. Delete all the items defined in the traceability tree.
	 */
	public void deleteTreeContents() {
		// Get the tree widget
		Tree t = (Tree)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_WIDGET_NAME);
		this.deleteTreeContents(t);
		
		// Show the empty edition panel
		this.showEmpty();
	}
	
	/**
	 * Delete the graphical traceability tree made of the traceability
	 * file. Delete all the items defined in the traceability tree.
	 * @param t Tree, 
	 */
	public void deleteTreeContents(Tree t) {
		// Get all the root items (tree items hang directly of the tree widget)
		TreeItem[] lItems = t.getItems();

		for (int i=0; lItems != null && i < lItems.length; i++) {
			this.deleteItem(this.items.get(lItems[i]));
		} // for each root tree item

		// Clear the items hash
		this.items.clear();
		this.itemsByName.clear();

		t.removeListener(SWT.Selection, new GenericListener("on_item_selected", this));
	}
	
	/**
	 * Build all the items of a parsed traceability tree.
	 * @param tree TraceabilityTree, tree constructed as the result
	 * of traceability file parsing.
	 * @param parent Widget, parent widget of the tree items that
	 * will be built.
	 */
	private void buildTreeContent(TraceabilityTree tree, Widget parent) {
		// Check if the parent widget is of type TreeView to hold the tree contents.
		if (!(parent instanceof Tree)) {
			System.err.println("There is not TreeView widget defined in the interface glade file!");
			System.exit(-1);
		}
		
		if (tree != null) {
			// Get the root node of the traceability tree (a product node)
			ProductInfo rootProduct = tree.getProduct();

			this.buildProductItem((Tree)parent, rootProduct);
		} // if tree is not null
	}

	/**
	 * Gets the Traceability tree item's catalog (indexed by widget).
	 * @return Hashtable<Widget, TraceabilityTreeItem>, catalog of items.
	 */
	public Hashtable<Widget, TraceabilityTreeItem> getItems() {
		return items;
	}

	/**
	 * Sets up the Traceability tree item's catalog (indexed by widget).
	 * @param items Hashtable<Widget, TraceabilityTreeItem>, a catalog of items.
	 */
	public void setItems(Hashtable<Widget, TraceabilityTreeItem> items) {
		this.items = items;
	}

	/**
	 * Gets if the insert mode is enabled.
	 * @return boolean, True when the insert mode is enabled; False when
	 * the insert mode is disabled.
	 */
	public boolean isInsertMode() {
		return insertMode;
	}

	/**
	 * Sets up the insert mode. 
	 * @param insertMode boolean, True to enable the insert mode; 
	 * False to disable the insert mode.
	 */
	public void setInsertMode(boolean insertMode) {
		this.insertMode = insertMode;
	}

	/**
	 * Gets the insert item type chosen by the user.
	 * @return int, insert item type.
 	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_UNDEFINED
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_PRODUCT
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_PROCESS
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_WORKER
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_WORKCENTER
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_WAREHOUSE
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_PURCHASE
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_PROPERTY
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_APPCC
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_COMMENT
	 */
	public int getInsertType() {
		return insertType;
	}

	/**
	 * Sets up the insert item type chosen by the user. 
	 * @param insertType int, an item type.
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_UNDEFINED
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_PRODUCT
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_PROCESS
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_WORKER
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_WORKCENTER
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_WAREHOUSE
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_PURCHASE
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_PROPERTY
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_APPCC
	 * @see org.ceteca.traceabilityTreeViewer.gui.TraceabilityTreeItem#NODE_COMMENT
	 */
	public void setInsertType(int insertType) {
		this.insertType = insertType;
	}

	/**
	 * Gets the Traceability tree item's catalog (indexed by name).
	 * @return Hashtable<String, TraceabilityTreeItem>, catalog of items.
	 */
	public Hashtable<String, TraceabilityTreeItem> getItemsByName() {
		return itemsByName;
	}

	/**
	 * Sets up the Traceability tree item's catalog (indexed by name).
	 * @param itemsByName Hashtable<String, TraceabilityTreeItem>, a catalog of items.
	 */
	public void setItemsByName(Hashtable<String, TraceabilityTreeItem> itemsByName) {
		this.itemsByName = itemsByName;
	}

	/**
	 * Gets the opened traceability file path.
	 * @return String, item name.
	 */
	public String getTraceabilityFilename() {
		return this.traceabilityFilename;
	}

	/**
	 * Sets up the opened traceability file path. 
	 * @param traceabilityFilename String, a traceability file path.
	 */
	public void setTraceabilityFilename(String traceabilityFilename) {
		this.traceabilityFilename = traceabilityFilename;
	}

	/**
	 * Builds a new tree item of type Product. It's used when the product
	 * item is the root of the tree.
	 * @param parent Tree, tree widget that will be the parent of the 
	 * product item.
	 * @param prodInfo ProductInfo, data of the product item to create.
	 * @return TraceabilityTreeItem, built product item.
	 */
	private TraceabilityTreeItem buildProductItem(Tree parent, ProductInfo prodInfo) {
		return this.buildProductItem(parent, prodInfo, -1);
	}
	
	/**
	 * Builds a new tree item of type Product. It's used when the product
	 * item is the root of the tree.
	 * @param parent Tree, tree widget that will be the parent of the 
	 * product item.
	 * @param prodInfo ProductInfo, data of the product item to create.
	 * @param index int, index the property item will be inserted at.
	 * @return TraceabilityTreeItem, built product item.
	 */
	private TraceabilityTreeItem buildProductItem(Tree parent, ProductInfo prodInfo, int index) {
		// Build the gui for the product node
		TraceabilityTreeItem rootItem = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				parent, 
				SWT.NONE, 
				prodInfo, 
				prodInfo.getDescription(), 
				InterfaceTraceabilityTree.ICON_PRODUCT_FILENAME,
				index
		);
		
		items.put(rootItem.getItemWidget(), rootItem);
		itemsByName.put("NODE_PRODUCT_" + prodInfo.getReference(), rootItem);
	
		// Add a new node for the reference code of the product node
		TraceabilityTreeItem item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				rootItem, 
				SWT.NONE, 
				prodInfo, 
				prodInfo.getReference(), 
				InterfaceTraceabilityTree.ICON_REFERENCE_FILENAME
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PRODUCT_" + prodInfo.getReference() + "_REFERENCE", item);
		
		// Add a new node for the set number of the product node
		item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				rootItem, 
				SWT.NONE, 
				prodInfo, 
				prodInfo.getSetNumber(), 
				InterfaceTraceabilityTree.ICON_SET_FILENAME
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PRODUCT_" + prodInfo.getReference() + "_SETNO", item);
		
		// Add a new node for the barcode of the product node
		item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				rootItem, 
				SWT.NONE, 
				prodInfo, 
				prodInfo.getBarcode(), 
				InterfaceTraceabilityTree.ICON_BARCODE_FILENAME
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PRODUCT_" + prodInfo.getReference() + "_BARCODE", item);
		
		// Add a new node for the in date of the product node
		item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				rootItem, 
				SWT.NONE, 
				prodInfo, 
				prodInfo.getDateIn(), 
				InterfaceTraceabilityTree.ICON_DATE_FILENAME
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PRODUCT_" + prodInfo.getReference() + "_DATEIN", item);
		
		// Add a new node for the expiry date of the product node
		item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				rootItem, 
				SWT.NONE, 
				prodInfo, 
				prodInfo.getDateExpiry(), 
				InterfaceTraceabilityTree.ICON_DATE_FILENAME
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PRODUCT_" + prodInfo.getReference() + "_DATEEXPIRY", item);

		// Add a new node for the traceability filename of the product node
		item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				rootItem, 
				SWT.NONE, 
				prodInfo, 
				(prodInfo.getTraceabilityFile()==null||prodInfo.getTraceabilityFile().length() <= 0)?"<no tr file>":prodInfo.getTraceabilityFile(), 
				InterfaceTraceabilityTree.ICON_TRFILENAME_FILENAME
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PRODUCT_" + prodInfo.getReference() + "_TRFILE", item);
		
		// Add the properties of the root product node
		for (int i=0; prodInfo.getLProperties() != null && i<prodInfo.getLProperties().size(); i++) {
			PropertyInfo propInfo = (PropertyInfo)prodInfo.getLProperties().get(i);
			// Add a new node for the property of the product node
			this.buildPropertyItem(rootItem, propInfo);
			
		} // for each product's property
		
		// Add the comments of the root product node
		for (int i=0; prodInfo.getLComments() != null && i<prodInfo.getLComments().size(); i++) {
			String comment = (String)prodInfo.getLComments().get(i);
			// Add a new node for the comment of the product node
			this.buildCommentItem(rootItem, comment);
		} // for each product's comment
		
		// Add the source of the product
		switch (prodInfo.getSourceType()) {
			case ProductInfo.SOURCE_PROCESS:
				ProcessInfo procInfo = prodInfo.getSourceProcess();
				this.buildProcessItem(rootItem, procInfo);
				break;
			case ProductInfo.SOURCE_PURCHASE:
				PurchaseInfo purcInfo = prodInfo.getSourcePurchase();
				this.buildPurchaseItem(rootItem, purcInfo);
				break;
		}
		
		// Add the warehouses of the root product node
		for (int i=0; prodInfo.getLWarehouses() != null && i<prodInfo.getLWarehouses().size(); i++) {
			WarehouseInfo wareInfo = (WarehouseInfo)prodInfo.getLWarehouses().get(i);
			// Add a new node for the warehouse of the product node
			this.buildWarehouseItem(rootItem, wareInfo);
		} // for each product's warehouse
		
		return rootItem;
	}

	/**
	 * Builds a new tree item of type Product. It's used when the product
	 * item is not the root of the tree (product is part of the input
	 * of a process).
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the product item.
	 * @param prodInfo ProductInfo, data of the product item to create.
	 * @return TraceabilityTreeItem, built product item.
	 */
	private TraceabilityTreeItem buildProductItem(TraceabilityTreeItem parent, ProductInfo prodInfo) {
		return this.buildProductItem(parent, prodInfo, -1);
	}
	
	/**
	 * Builds a new tree item of type Product. It's used when the product
	 * item is not the root of the tree (product is part of the input
	 * of a process).
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the product item.
	 * @param prodInfo ProductInfo, data of the product item to create.
	 * @param index int, index the property item will be inserted at.
	 * @return TraceabilityTreeItem, built product item.
	 */
	private TraceabilityTreeItem buildProductItem(TraceabilityTreeItem parent, ProductInfo prodInfo, int index) {
		// Build the gui for the product node
		TraceabilityTreeItem rootItem = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				parent, 
				SWT.NONE, 
				prodInfo, 
				prodInfo.getDescription(), 
				InterfaceTraceabilityTree.ICON_INPRODUCT_FILENAME,
				index
		);
		
		items.put(rootItem.getItemWidget(), rootItem);
		itemsByName.put("NODE_PRODUCT_" + prodInfo.getReference(), rootItem);
	
		// Add a new node for the reference code of the product node
		TraceabilityTreeItem item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				rootItem, 
				SWT.NONE, 
				prodInfo, 
				prodInfo.getReference(), 
				InterfaceTraceabilityTree.ICON_REFERENCE_FILENAME
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PRODUCT_" + prodInfo.getReference() + "_REFERENCE", item);
		
		// Add a new node for the set number of the product node
		item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				rootItem, 
				SWT.NONE, 
				prodInfo, 
				prodInfo.getSetNumber(), 
				InterfaceTraceabilityTree.ICON_SET_FILENAME
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PRODUCT_" + prodInfo.getReference() + "_SETNO", item);
		
		// Add a new node for the barcode of the product node
		item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				rootItem, 
				SWT.NONE, 
				prodInfo, 
				prodInfo.getBarcode(), 
				InterfaceTraceabilityTree.ICON_BARCODE_FILENAME
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PRODUCT_" + prodInfo.getReference() + "_BARCODE", item);
		
		// Add a new node for the in date of the product node
		item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				rootItem, 
				SWT.NONE, 
				prodInfo, 
				prodInfo.getDateIn(), 
				InterfaceTraceabilityTree.ICON_DATE_FILENAME
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PRODUCT_" + prodInfo.getReference() + "_DATEIN", item);
		
		// Add a new node for the expiry date of the product node
		item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				rootItem, 
				SWT.NONE, 
				prodInfo, 
				prodInfo.getDateExpiry(), 
				InterfaceTraceabilityTree.ICON_DATE_FILENAME
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PRODUCT_" + prodInfo.getReference() + "_DATEEXPIRY", item);

		// Add a new node for the traceability filename of the product node
		item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				rootItem, 
				SWT.NONE, 
				prodInfo, 
				(prodInfo.getTraceabilityFile()==null||prodInfo.getTraceabilityFile().length() <= 0)?"<no tr file>":prodInfo.getTraceabilityFile(), 
				InterfaceTraceabilityTree.ICON_TRFILENAME_FILENAME
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PRODUCT_" + prodInfo.getReference() + "_TRFILE", item);
		
		// Add the properties of the root product node
		for (int i=0; prodInfo.getLProperties() != null && i<prodInfo.getLProperties().size(); i++) {
			PropertyInfo propInfo = (PropertyInfo)prodInfo.getLProperties().get(i);
			// Add a new node for the property of the product node
			this.buildPropertyItem(rootItem, propInfo);
			
		} // for each product's property
		
		// Add the comments of the root product node
		for (int i=0; prodInfo.getLComments() != null && i<prodInfo.getLComments().size(); i++) {
			String comment = (String)prodInfo.getLComments().get(i);
			// Add a new node for the comment of the product node
			this.buildCommentItem(rootItem, comment);
		} // for each product's comment
		
		// Add the source of the product
		switch (prodInfo.getSourceType()) {
			case ProductInfo.SOURCE_PROCESS:
				ProcessInfo procInfo = prodInfo.getSourceProcess();
				this.buildProcessItem(rootItem, procInfo);
				break;
			case ProductInfo.SOURCE_PURCHASE:
				PurchaseInfo purcInfo = prodInfo.getSourcePurchase();
				this.buildPurchaseItem(rootItem, purcInfo);
				break;
		}
		
		// Add the warehouses of the root product node
		for (int i=0; prodInfo.getLWarehouses() != null && i<prodInfo.getLWarehouses().size(); i++) {
			WarehouseInfo wareInfo = (WarehouseInfo)prodInfo.getLWarehouses().get(i);
			// Add a new node for the warehouse of the product node
			this.buildWarehouseItem(rootItem, wareInfo);
		} // for each product's warehouse
		
		return rootItem;
	}

	/**
	 * Builds a new tree item of type Property.
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the property item.
	 * @param propInfo PropertyInfo, data of the property item to create.
	 * @return TraceabilityTreeItem, built property item.
	 */
	private TraceabilityTreeItem buildPropertyItem(TraceabilityTreeItem parent, PropertyInfo propInfo) {
		return this.buildPropertyItem(parent, propInfo, -1);
	}
	
	/**
	 * Builds a new tree item of type Property.
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the property item.
	 * @param propInfo PropertyInfo, data of the property item to create.
	 * @param index int, index the property item will be inserted at. 
	 * @return TraceabilityTreeItem, built property item.
	 */
	private TraceabilityTreeItem buildPropertyItem(TraceabilityTreeItem parent, PropertyInfo propInfo, int index) {
		// Build the gui for the property node
		TraceabilityTreeItem item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				parent, 
				SWT.NONE, 
				propInfo, 
				propInfo.getDescription() + " = " + propInfo.getVal(), 
				InterfaceTraceabilityTree.ICON_PROPERTY_FILENAME,
				index
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PRODUCT_" + ((ProductInfo)parent.getInfo()).getReference() + "_" + propInfo.getCod(), item);
		
		return item;
	}
	
	/**
	 * Builds a new tree item of type Process.
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the process item.
	 * @param procInfo ProcessInfo, data of the process item to create.
	 * @return TraceabilityTreeItem, built process item.
	 */
	private TraceabilityTreeItem buildProcessItem(TraceabilityTreeItem parent, ProcessInfo procInfo) {
		return this.buildProcessItem(parent, procInfo, -1);
	}
	
	/**
	 * Builds a new tree item of type Process.
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the process item.
	 * @param procInfo ProcessInfo, data of the process item to create.
	 * @param index int, index the process item will be inserted at. 
	 * @return TraceabilityTreeItem, built process item.
	 */
	private TraceabilityTreeItem buildProcessItem(TraceabilityTreeItem parent, ProcessInfo procInfo, int index) {
		// Build the gui for the process node
		TraceabilityTreeItem rootItem = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				parent, 
				SWT.NONE, 
				procInfo, 
				procInfo.getCodOperation(), 
				InterfaceTraceabilityTree.ICON_PROCESS_FILENAME,
				index
		);
		items.put(rootItem.getItemWidget(), rootItem);
		itemsByName.put("NODE_PROCESS_" + procInfo.getCodOperation(), rootItem);
		
		// Add a new node for the process date of the process node
		TraceabilityTreeItem item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				rootItem, 
				SWT.NONE, 
				procInfo, 
				procInfo.getDateProcess(), 
				InterfaceTraceabilityTree.ICON_DATE_FILENAME
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PROCESS_" + procInfo.getCodOperation() + "_DATE", item);
		
		// Add the input products of the process
		for (int i=0; procInfo.getLIn() != null && i<procInfo.getLIn().size(); i++) {
			ProductInfo prodInfo = (ProductInfo)procInfo.getLIn().get(i);
			// Add a new node for the worker of the process node
			this.buildProductItem(rootItem, prodInfo);
		} // for each process's worker
		
		// Add the workers of the process node
		for (int i=0; procInfo.getLWorkers() != null && i<procInfo.getLWorkers().size(); i++) {
			WorkerInfo workInfo = (WorkerInfo)procInfo.getLWorkers().get(i);
			// Add a new node for the worker of the process node
			this.buildWorkerItem(rootItem, workInfo);
		} // for each process's worker
		
		// Add the workcenters of the process node
		for (int i=0; procInfo.getLWorkcenters() != null && i<procInfo.getLWorkcenters().size(); i++) {
			WorkcenterInfo wcenInfo = (WorkcenterInfo)procInfo.getLWorkcenters().get(i);
			// Add a new node for the workcenter of the process node
			this.buildWorkcenterItem(rootItem, wcenInfo);
		} // for each process's workcenter
		
		// Add the comments of the process node
		for (int i=0; procInfo.getLComments() != null && i<procInfo.getLComments().size(); i++) {
			String comment = (String)procInfo.getLComments().get(i);
			// Add a new node for the comment of the process node
			this.buildCommentItem(rootItem, comment);
		} // for each process's comment
		
		return rootItem;
	}

	/**
	 * Builds a new tree item of type Purchase.
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the purchase item.
	 * @param purcInfo PurchaseInfo, data of the purchase item to create.
	 * @return TraceabilityTreeItem, built purchase item.
	 */
	private TraceabilityTreeItem buildPurchaseItem(TraceabilityTreeItem parent, PurchaseInfo purcInfo) {
		return this.buildPurchaseItem(parent, purcInfo, -1);
	}
	
	/**
	 * Builds a new tree item of type Purchase.
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the purchase item.
	 * @param purcInfo PurchaseInfo, data of the purchase item to create.
	 * @param index int, index the purchase item will be inserted at. 
	 * @return TraceabilityTreeItem, built purchase item.
	 */
	private TraceabilityTreeItem buildPurchaseItem(TraceabilityTreeItem parent, PurchaseInfo purcInfo, int index) {
		// Add a new node for the purchase of the product node
		TraceabilityTreeItem item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				parent, 
				SWT.NONE, 
				purcInfo, 
				purcInfo.getCodPurchaseConfirmation(), 
				InterfaceTraceabilityTree.ICON_PURCHASE_FILENAME,
				index
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_PURCHASE_" + purcInfo.getCodPurchaseConfirmation(), item);
		
		return item;
	}

	/**
	 * Builds a new tree item of type Warehouse.
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the warehouse item.
	 * @param wareInfo WarehouseInfo, data of the warehouse item to create.
	 * @return TraceabilityTreeItem, built warehouse item.
	 */
	private TraceabilityTreeItem buildWarehouseItem(TraceabilityTreeItem parent, WarehouseInfo wareInfo) {
		return this.buildWarehouseItem(parent, wareInfo, -1);
	}
	
	/**
	 * Builds a new tree item of type Warehouse.
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the warehouse item.
	 * @param wareInfo WarehouseInfo, data of the warehouse item to create.
	 * @param index int, index the warehouse item will be inserted at. 
	 * @return TraceabilityTreeItem, built warehouse item.
	 */	
	private TraceabilityTreeItem buildWarehouseItem(TraceabilityTreeItem parent, WarehouseInfo wareInfo, int index) {
		// Add a new node for the warehouse of the product node
		TraceabilityTreeItem item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				parent, 
				SWT.NONE, 
				wareInfo, 
				wareInfo.getDescription(), 
				InterfaceTraceabilityTree.ICON_WAREHOUSE_FILENAME,
				index
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_WAREHOUSE_" + wareInfo.getCodWarehouse(), item);
		
		return item;
	}

	/**
	 * Builds a new tree item of type Worker.
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the worker item.
	 * @param workInfo WorkerInfo, data of the worker item to create.
	 * @return TraceabilityTreeItem, built worker item.
	 */
	private TraceabilityTreeItem buildWorkerItem(TraceabilityTreeItem parent, WorkerInfo workInfo) {
		return this.buildWorkerItem(parent, workInfo, -1);
	}
	
	/**
	 * Builds a new tree item of type Worker.
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the worker item.
	 * @param workInfo WorkerInfo, data of the worker item to create.
	 * @param index int, index the worker item will be inserted at. 
	 * @return TraceabilityTreeItem, built worker item.
	 */
	private TraceabilityTreeItem buildWorkerItem(TraceabilityTreeItem parent, WorkerInfo workInfo, int index) {
		// Add a new node for the worker of the process node
		TraceabilityTreeItem item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				parent, 
				SWT.NONE, 
				workInfo, 
				workInfo.getDescription(), 
				InterfaceTraceabilityTree.ICON_WORKER_FILENAME,
				index
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_WORKER_" + workInfo.getCodWorker(), item);
		
		return item;
	}
	
	/**
	 * Builds a new tree item of type Workcenter.
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the workcenter item.
	 * @param wcenInfo WorkcenterInfo, data of the workcenter item to create.
	 * @return TraceabilityTreeItem, built workcenter item.
	 */
	private TraceabilityTreeItem buildWorkcenterItem(TraceabilityTreeItem parent, WorkcenterInfo wcenInfo) {
		return this.buildWorkcenterItem(parent, wcenInfo, -1);
	}
	
	/**
	 * Builds a new tree item of type Workcenter.
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the workcenter item.
	 * @param wcenInfo WorkcenterInfo, data of the workcenter item to create.
	 * @param index int, index the workcenter item will be inserted at. 
	 * @return TraceabilityTreeItem, built workcenter item.
	 */
	private TraceabilityTreeItem buildWorkcenterItem(TraceabilityTreeItem parent, WorkcenterInfo wcenInfo, int index) {
		// Add a new node for the workcenter of the process node
		TraceabilityTreeItem item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				parent, 
				SWT.NONE, 
				wcenInfo, 
				wcenInfo.getDescription(), 
				InterfaceTraceabilityTree.ICON_WORKCENTER_FILENAME,
				index
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_WORKCENTER_" + wcenInfo.getCodWorkcenter(), item);
		
		return item;
	}

	/**
	 * Builds a new tree item of type Comment.
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the comment item.
	 * @param comment String, data of the comment item to create.
	 * @return TraceabilityTreeItem, built comment item.
	 */
	private TraceabilityTreeItem buildCommentItem(TraceabilityTreeItem parent, String comment) {
		return this.buildCommentItem(parent, comment, -1);
	}
	
	/**
	 * Builds a new tree item of type Comment.
	 * @param parent TraceabilityTreeItem, item that will be the parent 
	 * of the comment item.
	 * @param comment String, data of the comment item to create.
	 * @param index int, index the comment item will be inserted at. 
	 * @return TraceabilityTreeItem, built comment item.
	 */
	private TraceabilityTreeItem buildCommentItem(TraceabilityTreeItem parent, String comment, int index) {
		// Add a new node for the comment of the product/process node
		TraceabilityTreeItem item = new TraceabilityTreeItem(
				ExplicaGUIBuilder.getInstance().getToolkit(), 
				parent, 
				SWT.NONE, 
				null, 
				comment, 
				InterfaceTraceabilityTree.ICON_COMMENT_FILENAME,
				this,
				"on_item_selected",
				index
		);
		items.put(item.getItemWidget(), item);
		itemsByName.put("NODE_COMMENT_" + comment, item);
		
		return item;
	}
	
	/**
	 * Handler for the item selected event.
	 * Loads the edition screen corresponding to the selected item and
	 * shows the item information on screen.  
	 * @param e Event, item selection event data.
	 */
	public void on_item_selected(Event e) {
		TraceabilityTreeItem itemSelected = this.items.get(e.item);
		LoggerFactory.getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY).
			info(String.format(InterfaceTraceabilityTree.TREEVIEW_LOG_SELECTEDITEM, itemSelected));
		
		this.showSelectedItem(itemSelected);
	}
	
	/**
	 * Gets the currently selected tree item.
	 * @return TraceabilityTreeItem, selected tree item.
	 */
	private TraceabilityTreeItem getSelectedTreeItem() {
		// Get the tree widget
		Tree t = (Tree)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_WIDGET_NAME);
		
		return this.getSelectedTreeItem(t);
	}

	/**
	 * Gets the currently selected tree item.
	 * @param tree Tree, Tree widget managed by the Tree Viewer.
	 * @return TraceabilityTreeItem, selected tree item.
	 */
	private TraceabilityTreeItem getSelectedTreeItem(Tree tree) {
		TraceabilityTreeItem itemSelected = null;
	
		TreeItem[] selectedItems = tree.getSelection();
		if (selectedItems != null && selectedItems.length > 0) {
			TreeItem item = selectedItems[0];
			itemSelected = this.items.get(item);
			LoggerFactory.getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY).
				debug(String.format(InterfaceTraceabilityTree.TREEVIEW_LOG_SELECTEDITEM, itemSelected));
		}
		
		return itemSelected;
	}
	
	/**
	 * Shows the selected item data in the edition panel (right side of
	 * the screen).
	 * @param itemSelected TraceabilityTreeItem, selected tree item to show.
	 */
	private void showSelectedItem(TraceabilityTreeItem itemSelected) {
		Composite rootComposite = null;
		Widget w = null;

		// Get the root composite where the edition panels are embedded
		rootComposite = (Composite)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PANEL_NAME);
		
		// Show the edition panel suitable for the type of node selected
		if (itemSelected == null) {
			w = this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_EMPTY_PANEL_NAME);
		} // if no item has been selected
		else {
			switch (itemSelected.getType()) {
				// if selected node == PRODUCT
				case TraceabilityTreeItem.NODE_PRODUCT:
					w = this.getEditProductGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PRODUCT_PANEL_NAME);
					this.showProduct((ProductInfo)itemSelected.getInfo());
					break;
				// if selected node == PURCHASE
				case TraceabilityTreeItem.NODE_PURCHASE:
					w = this.getEditPurchaseGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PURCHASE_PANEL_NAME);
					this.showPurchase((PurchaseInfo)itemSelected.getInfo());
					break;
				// if selected node == PROPERTY
				case TraceabilityTreeItem.NODE_PROPERTY:
					w = this.getEditPropertyGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PROPERTY_PANEL_NAME);
					this.showProperty((PropertyInfo)itemSelected.getInfo());
					break;
				// if selected node == WAREHOUSE
				case TraceabilityTreeItem.NODE_WAREHOUSE:
					w = this.getEditWarehouseGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_WAREHOUSE_PANEL_NAME);
					this.showWarehouse((WarehouseInfo)itemSelected.getInfo());
					break;
				// if selected node == COMMENT
				case TraceabilityTreeItem.NODE_COMMENT:
					w = this.getEditCommentGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_COMMENT_PANEL_NAME);
					this.showComment(itemSelected.getItemWidget().getText());
					break;
				// if selected node == PROCESS
				case TraceabilityTreeItem.NODE_PROCESS:
					w = this.getEditProcessGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PROCESS_PANEL_NAME);
					this.showProcess((ProcessInfo)itemSelected.getInfo());
					break;
				// if selected node == WORKER
				case TraceabilityTreeItem.NODE_WORKER:
					w = this.getEditWorkerGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_WORKER_PANEL_NAME);
					this.showWorker((WorkerInfo)itemSelected.getInfo());
					break;
				// if selected node == WORKCENTER
				case TraceabilityTreeItem.NODE_WORKCENTER:
					w = this.getEditWorkcenterGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_WORKCENTER_PANEL_NAME);
					this.showWorkcenter((WorkcenterInfo)itemSelected.getInfo());
					break;
				// if selected node == APPCC
				case TraceabilityTreeItem.NODE_APPCC:
					w = this.getEditAppccGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_APPCC_PANEL_NAME);
//					this.showAppcc((AppccInfo)itemSelected.getInfo());
					break;
				// if selected node == UNDEFINED
				case TraceabilityTreeItem.NODE_UNDEFINED:
					w = this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_EMPTY_PANEL_NAME);
					break;
			} // switch
		} // else an item has been selected

		if (w != null && rootComposite != null) {
			((StackLayout)rootComposite.getLayout()).topControl = (Control)w;
			rootComposite.layout(true, true);
//			this.gui.getParentWindow().getShell().layout(true, true);
		}
	}
	
	/**
	 * Builds the edition panel widget (right side of the screen) that
	 * will hold the detailed data of the tree items.
	 * @param editGuiName String, name of the edition GUI.
	 * @param panelName String, code of the Edition Panel type to build.
	 * @param editGladePath String, complete path of the glade file that
	 * keeps the edition panel GUI definition.
	 * @param rootComposite Composite, composite widget that will hold
	 * the built edition panel. 
	 */
	private void buildEditPanel(String editGuiName, String panelName, String editGladePath, Composite rootComposite) {
		// Build the comment edition panel
		Localizer oldLoc = JavaGladeUtil.getInstance().getLocalizer();
		try {
			URL url = this.getClass().getResource(editGladePath);
			JavaGladeUtil.getInstance().setLocalizer(this);
			LoggerFactory.getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY).
				info(String.format(InterfaceTraceabilityTree.TREEVIEW_LOG_EDITPANEL_PATH, panelName, (url == null?"null":url.getPath())));
			Gui editGui = ExplicaGUIBuilder.getInstance().buildGUI(editGuiName, editGladePath, this.gui, panelName, rootComposite, InterfaceTraceabilityTree.TREEVIEW_EDIT_PANEL_NAME, ClientContext.getInstance().getResourceDir());
//			this.gui.addChild(editGui);
			// Link the edition GUI with the accept/cancel buttons of the edition panel
			Widget acceptButton = null;
			Widget cancelButton = null;
			String[] s = {"Product", "Purchase", "Property", "Process", "Comment", "Appcc", "Worker", "Workcenter", "Warehouse"};
			try {
				for (int i=0; acceptButton == null && i<s.length; i++)  {
					acceptButton = editGui.getWidget(String.format("button%sAccept", s[i]));
					cancelButton = editGui.getWidget(String.format("button%sCancel", s[i]));
				}
			}
			catch (Exception ex) {
				acceptButton = null;
			}
			if (acceptButton != null && cancelButton != null) {
				acceptButton.setData(editGui);
				cancelButton.setData(editGui);
			}
		}
		catch (JavaGladeException jEx) {
			jEx.printStackTrace();
		}
		finally {
			JavaGladeUtil.getInstance().setLocalizer(oldLoc);
		}
	}

	private void showItem(Object info) {
		if (info instanceof ProductInfo)
			this.showProduct((ProductInfo)info);
		else if (info instanceof PropertyInfo)
			this.showProperty((PropertyInfo)info);
		else if (info instanceof WarehouseInfo)
			this.showWarehouse((WarehouseInfo)info);
//		else if (info instanceof AppccInfo)
//			this.showAppcc((AppccInfo)info);
		else if (info instanceof PurchaseInfo)
			this.showPurchase((PurchaseInfo)info);
		else if (info instanceof ProcessInfo)
			this.showProcess((ProcessInfo)info);
		else if (info instanceof WorkerInfo)
			this.showWorker((WorkerInfo)info);
		else if (info instanceof WorkcenterInfo)
			this.showWorkcenter((WorkcenterInfo)info);
		else if (info instanceof String)
			this.showComment((String)info);
	}

	/**
	 * Shows the product data in the Edition Panel.
	 * @param info ProductInfo, product data.
	 */
	private void showProduct(ProductInfo info) {
		Gui editGui = this.getEditProductGui();
		if (editGui == null)
			this.showEmpty();
		else {
			// Set up product reference
			Text t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_REFERENCE_ITEMNAME);
			t.setText(info==null?"":info.getReference());
			t.setBackground(null);
			// Set up product set number
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_SETNUMBER_ITEMNAME);
			t.setText(info==null?"":info.getSetNumber());
			t.setBackground(null);
			// Set up product barcode
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_BARCODE_ENTRY_ITEMNAME);
			t.setText(info==null?"":info.getBarcode());
			t.setBackground(null);
			Label l = (Label)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_BARCODE_IMAGE_ITEMNAME);
			Image img = null;
			if (info != null && info.getBarcode() != null && info.getBarcode().length() > 0) {
				img = BarcodeGenerator.createBarcodeImage(info.getBarcode(), ExplicaGUIBuilder.getInstance().getDisplay());
			}
			l.setImage(img);
			// Set up product description
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_DESCRIPTION_ITEMNAME);
			t.setText(info==null?"":info.getDescription());
			t.setBackground(null);
			// Set up product in date
			DateTime dateIn = null;
			if (info != null) {
				dateIn = new DateTime(info.getDateIn(), InterfaceTraceabilityTree.CONST_SHORT_DATE_PATTERN);
				if (dateIn != null && dateIn.getDate() == null)
					dateIn = null;
			}
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_IN_DAY_ITEMNAME);
			t.setText(dateIn==null?"":dateIn.getDay());
			t.setBackground(null);
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_IN_MONTH_ITEMNAME);
			t.setText(dateIn==null?"":dateIn.getMonth());
			t.setBackground(null);
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_IN_YEAR_ITEMNAME);
			t.setText(dateIn==null?"":dateIn.getYear());
			t.setBackground(null);
			// Set up product expiry date
			DateTime dateExpiry = null;
			if (info != null) {
				dateExpiry = new DateTime(info.getDateExpiry(), InterfaceTraceabilityTree.CONST_SHORT_DATE_PATTERN);
				if (dateExpiry != null && dateExpiry.getDate() == null)
					dateExpiry = null;
			}
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_EXPIRY_DAY_ITEMNAME);
			t.setText(dateExpiry==null?"":dateExpiry.getDay());
			t.setBackground(null);
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_EXPIRY_MONTH_ITEMNAME);
			t.setText(dateExpiry==null?"":dateExpiry.getMonth());
			t.setBackground(null);
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_EXPIRY_YEAR_ITEMNAME);
			t.setText(dateExpiry==null?"":dateExpiry.getYear());
			t.setBackground(null);
			// Set up product traceability filename
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_TRFILE_ITEMNAME);
			t.setText(info==null||info.getTraceabilityFile()==null?"":info.getTraceabilityFile());
			t.setBackground(null);
		}
	}
	
	/**
	 * Shows the purchase data in the Edition Panel.
	 * @param info PurchaseInfo, purchase data.
	 */
	private void showPurchase(PurchaseInfo info) {
		Gui editGui = this.getEditPurchaseGui();
		if (editGui == null)
			this.showEmpty();
		else {
			// Set up purchase code
			Text t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PURCHASE_CODE_ITEMNAME);
			t.setText(info==null?"":info.getCodPurchaseConfirmation());
			t.setBackground(null);
			// Set up purchase supplier
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PURCHASE_SUPPLIER_ITEMNAME);
			t.setText(info==null?"":info.getCodSupplier());
			t.setBackground(null);
		}
	}
	
	/**
	 * Shows the property data in the Edition Panel.
	 * @param info PropertyInfo, property data.
	 */
	private void showProperty(PropertyInfo info) {
		Gui editGui = this.getEditPropertyGui();
		if (editGui == null)
			this.showEmpty();
		else {
			// Set up property code
			Text t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROPERTY_CODE_ITEMNAME);
			t.setText(info==null?"":info.getCod());
			t.setBackground(null);
			// Set up property description
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROPERTY_DESCRIPTION_ITEMNAME);
			t.setText(info==null?"":info.getDescription());
			t.setBackground(null);
			// Set up property type
			Combo c = (Combo)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROPERTY_TYPE_ITEMNAME);
			if (info != null)
				c.select(info.getType());
			c.setBackground(null);
			// Set up property value
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROPERTY_VALUE_ITEMNAME);
			if (info == null)
				t.setText("");
			else {
				switch (info.getType()) {
					case PropertyInfo.PROPERTY_TYPE_BOOLEAN:
					case PropertyInfo.PROPERTY_TYPE_STRING:
					case PropertyInfo.PROPERTY_TYPE_NUMBER:
						t.setText(info==null?"":info.getVal().toString());
						break;
					case PropertyInfo.PROPERTY_TYPE_DATE:
						t.setText(info==null?"":((DateTime)info.getVal()).getDateAsString());
						break;
					case PropertyInfo.PROPERTY_TYPE_OBJECT:
						t.setText(info==null?"":info.getVal().toString());
						break;
				} // switch property type
			} // else info != null
			t.setBackground(null);
			
			// Set up property pattern
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROPERTY_PATTERN_ITEMNAME);
			if (info == null || info.getPattern() == null)
				t.setText("");
			else
				t.setText(info.getPattern());
			t.setBackground(null);
		}
	}
	
	/**
	 * Shows the warehouse data in the Edition Panel.
	 * @param info WarehouseInfo, warehouse data.
	 */
	private void showWarehouse(WarehouseInfo info) {
		Gui editGui = this.getEditWarehouseGui();
		if (editGui == null)
			this.showEmpty();
		else {
			// Set up warehouse code
			Text t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_WAREHOUSE_CODE_ITEMNAME);
			t.setText(info==null?"":info.getCodWarehouse());
			t.setBackground(null);
			// Set up warehouse description
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_WAREHOUSE_DESCRIPTION_ITEMNAME);
			t.setText(info==null?"":info.getDescription());
			t.setBackground(null);
		}
	}
	
	/**
	 * Shows the comment data in the Edition Panel.
	 * @param comment String, comment data.
	 */
	private void showComment(String comment) {
		Gui editGui = this.getEditCommentGui();
		if (editGui == null)
			this.showEmpty();
		else {
			// Set up comment text
			StyledText t = (StyledText)editGui.getWidget(InterfaceTraceabilityTree.EDIT_COMMENT_ITEMNAME);
			t.setText(comment==null?"":comment);
			t.setBackground(null);
		}
	}
	
	/**
	 * Shows the process data in the Edition Panel.
	 * @param info ProcessInfo, process data.
	 */
	private void showProcess(ProcessInfo info) {
		Gui editGui = this.getEditProcessGui();
		if (editGui == null)
			this.showEmpty();
		else {
			// Set up process code
			Text t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROCESS_CODE_ITEMNAME);
			t.setText(info==null?"":info.getCodOperation());
			t.setBackground(null);
			// Set up process date
			DateTime dateProcess = null;
			if (info != null) {
				dateProcess = new DateTime(info.getDateProcess(), InterfaceTraceabilityTree.CONST_SHORT_DATE_PATTERN);
				if (dateProcess != null && dateProcess.getDate() == null)
					dateProcess = null;
			}
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROCESS_DAY_ITEMNAME);
			t.setText(dateProcess==null?"":dateProcess.getDay());
			t.setBackground(null);
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROCESS_MONTH_ITEMNAME);
			t.setText(dateProcess==null?"":dateProcess.getMonth());
			t.setBackground(null);
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROCESS_YEAR_ITEMNAME);
			t.setText(dateProcess==null?"":dateProcess.getYear());
			t.setBackground(null);
		}
	}
	
	/**
	 * Shows the woker data in the Edition Panel.
	 * @param info WorkerInfo, worker data.
	 */
	private void showWorker(WorkerInfo info) {
		Gui editGui = this.getEditWorkerGui();
		if (editGui == null)
			this.showEmpty();
		else {
			// Set up worker code
			Text t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_WORKER_CODE_ITEMNAME);
			t.setText(info==null?"":info.getCodWorker());
			t.setBackground(null);
			// Set up warehouse description
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_WORKER_NAME_ITEMNAME);
			t.setText(info==null?"":info.getDescription());
			t.setBackground(null);
		}
	}
	
	/**
	 * Shows the workcenter data in the Edition Panel.
	 * @param info WorkcenterInfo, workcenter data.
	 */
	private void showWorkcenter(WorkcenterInfo info) {
		Gui editGui = this.getEditWorkcenterGui();
		if (editGui == null)
			this.showEmpty();
		else {
			// Set up warehouse code
			Text t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_WORKCENTER_CODE_ITEMNAME);
			t.setText(info==null?"":info.getCodWorkcenter());
			t.setBackground(null);
			// Set up warehouse description
			t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_WORKCENTER_DESCRIPTION_ITEMNAME);
			t.setText(info==null?"":info.getDescription());
			t.setBackground(null);
		}
	}
	
	/**
	 * Empties the Edition Panel.
	 */
	private void showEmpty() {
		Widget w = this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_EMPTY_PANEL_NAME);
		
		// Get the root composite where the edition panels are embedded
		Composite rootComposite = (Composite)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PANEL_NAME);
		
		if (w != null && rootComposite != null) {
			((StackLayout)rootComposite.getLayout()).topControl = (Control)w;
			rootComposite.layout(true, true);
		}
	}
	
	/**
	 * Fills the Property type combo in the Property's edition panel. 
	 * @param jg JavaGlade, JavaGlade instance used in the construction
	 * of the Traceability Tree Viewer GUI.
	 */
	private void fillPropertyTypeCombo() {
		Combo c = (Combo)this.getEditPropertyGui().getWidget(InterfaceTraceabilityTree.EDIT_PROPERTY_TYPE_ITEMNAME);
		
		fillCombo(c, this.getPropertyTypeCollection());
	}

	/**
	 * Set the combo options
	 * @param c Combo, combo widget to be filled.
	 * @param items String[], list of options of the combo.
	 */
	private void fillCombo(Combo c, String[] items) {
		if (c != null && items != null && items.length > 0) {
			for (int i=0; i<items.length; i++) {
				c.add(items[i]);
			} // for each item
		}
	}
	
	/**
	 * Handler for the accept button pressed event.
	 * Updates the tree to keep the changes made to the traceability 
	 * tree.
	 * @param e Event, accept button pressed event data.
	 */
	public void on_accept_pressed(Event e) {
		Gui editGui = (Gui)e.widget.getData();
	
		Tree t = (Tree)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_WIDGET_NAME);
		
		TraceabilityTreeItem itemSelected = this.getSelectedTreeItem(t);
		
		// Update the info of the node selected
		if (this.isInsertMode()) {
			Object info = this.getInfoData(editGui, this.insertType);
			
			// Reset the colour of the form widgets
			this.showItem(info);
			
			// If the node is of type Product the selected node must be the root node of
			// the product and not any of the child nodes that show properties of the product.
			if (itemSelected != null && itemSelected.getInfo() instanceof ProductInfo) {
				String nodeName = "NODE_PRODUCT_" + ((ProductInfo)itemSelected.getInfo()).getReference();
				if (!itemSelected.getName().equals(nodeName))
					itemSelected = this.itemsByName.get(nodeName);
			}
			// If the node is of type Process the selected node must be the root node of
			// the process and not any of the child nodes that show properties of the process.
			else if (itemSelected != null && itemSelected.getInfo() instanceof ProcessInfo) {
				String nodeName = "NODE_PROCESS_" + ((ProcessInfo)itemSelected.getInfo()).getCodOperation();
				if (!itemSelected.getName().equals(nodeName))
					itemSelected = this.itemsByName.get(nodeName);
			}
			
			// Validate the item info typed by the user
			ArrayList<ResultMessage> lResultValidation = TraceabilityTreeBLL.getInstance().
				validateTreeItem(this.insertType, info, itemSelected == null? TraceabilityTreeItem.NODE_UNDEFINED:itemSelected.getType());
			
			if (TraceabilityTreeBLL.getInstance().isTreeItemCorrect(lResultValidation)) {
				if (itemSelected == null) {
					// Add a selection listener to capture the selection of tree items events
					t.addListener(SWT.Selection, new GenericListener("on_item_selected", this));

					this.buildNewTreeItem(t, this.insertType, info);
				}
				else {
					this.buildNewTreeItem(itemSelected, this.insertType, info);
				}
				
				// Update the status bar to show the default mode
				StatusBar sBar = (StatusBar)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_STATUSBAR_WIDGET_NAME);
				if (sBar != null)
					sBar.updateStatus(InterfaceTraceabilityTree.TREEVIEW_STATUSBAR_DEFAULT_TEXT);
				
				// Unset the insert mode
				this.setInsertMode(false);
				this.setInsertType(TraceabilityTreeItem.NODE_UNDEFINED);
			} // if the new item is valid and is placed in the right place
			else {
				this.showResultMessages(editGui, lResultValidation);
			} // else item invalid or missplaced
		} // if no item has been selected
		else if (itemSelected != null) {
			switch (itemSelected.getType()) {
				// if selected node == PRODUCT
				case TraceabilityTreeItem.NODE_PRODUCT:
					updateProductNode(itemSelected);
					break;
				// if selected node == PURCHASE
				case TraceabilityTreeItem.NODE_PURCHASE:
					updatePurchaseNode(itemSelected);
					break;
				// if selected node == PROPERTY
				case TraceabilityTreeItem.NODE_PROPERTY:
					updatePropertyNode(itemSelected);
					break;
				// if selected node == WAREHOUSE
				case TraceabilityTreeItem.NODE_WAREHOUSE:
					updateWarehouseNode(itemSelected);
					break;
				// if selected node == COMMENT
				case TraceabilityTreeItem.NODE_COMMENT:
					updateCommentNode(itemSelected);
					break;
				// if selected node == PROCESS
				case TraceabilityTreeItem.NODE_PROCESS:
					updateProcessNode(itemSelected);
					break;
				// if selected node == WORKER
				case TraceabilityTreeItem.NODE_WORKER:
					updateWorkerNode(itemSelected);
					break;
				// if selected node == WORKCENTER
				case TraceabilityTreeItem.NODE_WORKCENTER:
					updateWorkcenterNode(itemSelected);
					break;
				// if selected node == APPCC
				case TraceabilityTreeItem.NODE_APPCC:
					break;
				// if selected node == UNDEFINED
				case TraceabilityTreeItem.NODE_UNDEFINED:
					break;
			} // switch
		} // else an item has been selected
	}
	
	/**
	 * Handler for the cancel button pressed event.
	 * Discards the changes made to the tree item and reloads the 
	 * previous item data.  
	 * @param e Event, cancel button pressed event data.
	 */
	public void on_cancel_pressed(Event e) {
		// Get the selected tree item
		TraceabilityTreeItem itemSelected = this.getSelectedTreeItem();
		
		// Show the selected tree item
		if (itemSelected == null) {
		} // if no item has been selected}
		else {
			this.showSelectedItem(itemSelected);
		} // else an item has been selected 
		
		// Update the status bar to show the default mode
		StatusBar sBar = (StatusBar)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_STATUSBAR_WIDGET_NAME);
		if (sBar != null)
			sBar.updateStatus(InterfaceTraceabilityTree.TREEVIEW_STATUSBAR_DEFAULT_TEXT);
	}
	
	/**
	 * Update the data of a product item with the changes made up by the user. 
	 * @param item TraceabilityTreeItem, modified product item.
	 */
	private void updateProductNode(TraceabilityTreeItem item) {
		Gui editGui = ExplicaGUIBuilder.getInstance().getGui(InterfaceTraceabilityTree.TREEVIEW_EDIT_PRODUCT_GUINAME);
		ProductInfo info = (ProductInfo)this.getInfoData(editGui, TraceabilityTreeItem.NODE_PRODUCT);

		// Check if the product reference has been changed
		boolean refChanged = false;
		refChanged = !info.getReference().equals(((ProductInfo)item.getInfo()).getReference());
		
		// Get all the tree nodes that show product information
		TraceabilityTreeItem itemProductRef = this.itemsByName.get("NODE_PRODUCT_" + ((ProductInfo)item.getInfo()).getReference() + "_REFERENCE");
		TraceabilityTreeItem itemProductSet = this.itemsByName.get("NODE_PRODUCT_" + ((ProductInfo)item.getInfo()).getReference() + "_SETNO");
		TraceabilityTreeItem itemProductBarcode = this.itemsByName.get("NODE_PRODUCT_" + ((ProductInfo)item.getInfo()).getReference() + "_BARCODE");
		TraceabilityTreeItem itemProductDes = this.itemsByName.get("NODE_PRODUCT_" + ((ProductInfo)item.getInfo()).getReference());
		TraceabilityTreeItem itemProductDateIn = this.itemsByName.get("NODE_PRODUCT_" + ((ProductInfo)item.getInfo()).getReference() + "_DATEIN");
		TraceabilityTreeItem itemProductDateExpiry = this.itemsByName.get("NODE_PRODUCT_" + ((ProductInfo)item.getInfo()).getReference() + "_DATEEXPIRY");
		TraceabilityTreeItem itemProductTrFile = this.itemsByName.get("NODE_PRODUCT_" + ((ProductInfo)item.getInfo()).getReference() + "_TRFILE");
		
		// Update info object linked to the tree items
		itemProductRef.updateInfo(info);
		itemProductSet.updateInfo(info);
		itemProductBarcode.updateInfo(info);
		itemProductDes.updateInfo(info);
		itemProductDateIn.updateInfo(info);
		itemProductDateExpiry.updateInfo(info);
		itemProductTrFile.updateInfo(info);
		
		// Update the tree item text that is showed in the tree viewer 
		itemProductRef.getItemWidget().setText(info.getReference());
		itemProductSet.getItemWidget().setText(info.getSetNumber());
		itemProductBarcode.getItemWidget().setText(info.getBarcode());
		itemProductDes.getItemWidget().setText(info.getDescription());
		itemProductDateIn.getItemWidget().setText(info.getDateIn());
		itemProductDateExpiry.getItemWidget().setText(info.getDateExpiry());
		itemProductTrFile.getItemWidget().setText(info.getTraceabilityFile());
		
		// Update the internal hashtable when the reference of the product has changed
		if (refChanged) {
			this.itemsByName.remove("NODE_PRODUCT_" + ((ProductInfo)item.getInfo()).getReference() + "_REFERENCE");
			this.itemsByName.put("NODE_PRODUCT_" + info.getReference() + "_REFERENCE", itemProductRef);
			this.itemsByName.remove("NODE_PRODUCT_" + ((ProductInfo)item.getInfo()).getReference() + "_SETNO");
			this.itemsByName.put("NODE_PRODUCT_" + info.getReference() + "_SETNO", itemProductSet);
			this.itemsByName.remove("NODE_PRODUCT_" + ((ProductInfo)item.getInfo()).getReference() + "_BARCODE");
			this.itemsByName.put("NODE_PRODUCT_" + info.getReference() + "_BARCODE", itemProductBarcode);
			this.itemsByName.remove("NODE_PRODUCT_" + ((ProductInfo)item.getInfo()).getReference());
			this.itemsByName.put("NODE_PRODUCT_" + info.getReference(), itemProductDes);
			this.itemsByName.remove("NODE_PRODUCT_" + ((ProductInfo)item.getInfo()).getReference() + "_DATEIN");
			this.itemsByName.put("NODE_PRODUCT_" + info.getReference() + "_DATEIN", itemProductDateIn);
			this.itemsByName.remove("NODE_PRODUCT_" + ((ProductInfo)item.getInfo()).getReference() + "_DATEEXPIRY");
			this.itemsByName.put("NODE_PRODUCT_" + info.getReference() + "_DATEEXPIRY", itemProductDateExpiry);
			this.itemsByName.remove("NODE_PRODUCT_" + ((ProductInfo)item.getInfo()).getReference() + "_TRFILE");
			this.itemsByName.put("NODE_PRODUCT_" + info.getReference() + "_TRFILE", itemProductTrFile);
		} // if ref has changed
	}
	
	/**
	 * Update the data of a property item with the changes made up by the user. 
	 * @param jg JavaGlade, JavaGlade instance used in the construction
	 * of the Traceability Tree Viewer GUI.
	 * @param item TraceabilityTreeItem, modified property item.
	 */
	private void updatePropertyNode(TraceabilityTreeItem item) {
		Gui editGui = ExplicaGUIBuilder.getInstance().getGui(InterfaceTraceabilityTree.TREEVIEW_EDIT_PROPERTY_GUINAME);
		PropertyInfo info = (PropertyInfo)this.getInfoData(editGui, TraceabilityTreeItem.NODE_PROPERTY);
		
		// Update info object linked to the tree item
		item.updateInfo(info);
		
		// Update the tree item text that is showed in the tree viewer
		item.getItemWidget().setText(info.getDescription() + " = " + info.getVal());
	}
	
	/**
	 * Update the data of a process item with the changes made up by the user. 
	 * @param jg JavaGlade, JavaGlade instance used in the construction
	 * of the Traceability Tree Viewer GUI.
	 * @param item TraceabilityTreeItem, modified process item.
	 */
	private void updateProcessNode(TraceabilityTreeItem item) {
		Gui editGui = ExplicaGUIBuilder.getInstance().getGui(InterfaceTraceabilityTree.TREEVIEW_EDIT_PROCESS_GUINAME);
		ProcessInfo info = (ProcessInfo)this.getInfoData(editGui, TraceabilityTreeItem.NODE_PROCESS);
		
		// Checks if the process code has been changed
		boolean codChanged = false;
		codChanged = !info.getCodOperation().equals(((ProcessInfo)item.getInfo()).getCodOperation());
		
		// Get all the tree nodes that show process information
		TraceabilityTreeItem itemProcess = this.itemsByName.get("NODE_PROCESS_" + info.getCodOperation());
		TraceabilityTreeItem itemProcessDate = this.itemsByName.get("NODE_PROCESS_" + info.getCodOperation() + "_DATE");
		
		// Update info object linked to the tree items
		itemProcess.updateInfo(info);
		itemProcessDate.updateInfo(info);
		
		// Update the tree item text that is showed in the tree viewer 
		itemProcess.getItemWidget().setText(info.getCodOperation());
		itemProcessDate.getItemWidget().setText(info.getDateProcess());
		
		// Update the internal hashtable when the code of the process has changed
		if (codChanged) {
			this.itemsByName.remove("NODE_PROCESS_" + ((ProcessInfo)item.getInfo()).getCodOperation());
			this.itemsByName.put("NODE_PROCESS_" + info.getCodOperation(), itemProcess);
			this.itemsByName.remove("NODE_PROCESS_" + ((ProcessInfo)item.getInfo()).getCodOperation() + "_DATE");
			this.itemsByName.put("NODE_PROCESS_" + info.getCodOperation() + "_DATE", itemProcessDate);
		} // if process code has changed
	}
	
	/**
	 * Update the data of a purchase item with the changes made up by the user. 
	 * @param jg JavaGlade, JavaGlade instance used in the construction
	 * of the Traceability Tree Viewer GUI.
	 * @param item TraceabilityTreeItem, modified purchase item.
	 */
	private void updatePurchaseNode(TraceabilityTreeItem item) {
		Gui editGui = ExplicaGUIBuilder.getInstance().getGui(InterfaceTraceabilityTree.TREEVIEW_EDIT_PURCHASE_GUINAME);
		PurchaseInfo info = (PurchaseInfo)this.getInfoData(editGui, TraceabilityTreeItem.NODE_PURCHASE);
		
		// Update info object linked to the tree item
		item.updateInfo(info);
		
		// Update the tree item text that is showed in the tree viewer
		item.getItemWidget().setText(info.getCodPurchaseConfirmation());
	}
	
	/**
	 * Update the data of a warehouse item with the changes made up by the user. 
	 * @param jg JavaGlade, JavaGlade instance used in the construction
	 * of the Traceability Tree Viewer GUI.
	 * @param item TraceabilityTreeItem, modified warehouse item.
	 */
	private void updateWarehouseNode(TraceabilityTreeItem item) {
		Gui editGui = ExplicaGUIBuilder.getInstance().getGui(InterfaceTraceabilityTree.TREEVIEW_EDIT_WAREHOUSE_GUINAME);
		WarehouseInfo info = (WarehouseInfo)this.getInfoData(editGui, TraceabilityTreeItem.NODE_WAREHOUSE);
		
		// Update info object linked to the tree item
		item.updateInfo(info);
		
		// Update the tree item text that is showed in the tree viewer
		item.getItemWidget().setText(info.getDescription());
	}
	
	/**
	 * Update the data of a worker item with the changes made up by the user. 
	 * @param jg JavaGlade, JavaGlade instance used in the construction
	 * of the Traceability Tree Viewer GUI.
	 * @param item TraceabilityTreeItem, modified worker item.
	 */
	private void updateWorkerNode(TraceabilityTreeItem item) {
		Gui editGui = ExplicaGUIBuilder.getInstance().getGui(InterfaceTraceabilityTree.TREEVIEW_EDIT_WORKER_GUINAME);
		WorkerInfo info = (WorkerInfo)this.getInfoData(editGui, TraceabilityTreeItem.NODE_WORKER);
		
		// Update info object linked to the tree item
		item.updateInfo(info);
		
		// Update the tree item text that is showed in the tree viewer
		item.getItemWidget().setText(info.getDescription());
	}
	
	/**
	 * Update the data of a workcenter item with the changes made up by the user. 
	 * @param jg JavaGlade, JavaGlade instance used in the construction
	 * of the Traceability Tree Viewer GUI.
	 * @param item TraceabilityTreeItem, modified workcenter item.
	 */
	private void updateWorkcenterNode(TraceabilityTreeItem item) {
		Gui editGui = ExplicaGUIBuilder.getInstance().getGui(InterfaceTraceabilityTree.TREEVIEW_EDIT_WORKCENTER_GUINAME);
		WorkcenterInfo info = (WorkcenterInfo)this.getInfoData(editGui, TraceabilityTreeItem.NODE_WORKCENTER);
		
		// Update info object linked to the tree item
		item.updateInfo(info);
		
		// Update the tree item text that is showed in the tree viewer
		item.getItemWidget().setText(info.getDescription());
	}
	
	/**
	 * Update the data of a comment item with the changes made up by the user. 
	 * @param jg JavaGlade, JavaGlade instance used in the construction
	 * of the Traceability Tree Viewer GUI.
	 * @param item TraceabilityTreeItem, modified comment item.
	 */
	private void updateCommentNode(TraceabilityTreeItem item) {
		Gui editGui = ExplicaGUIBuilder.getInstance().getGui(InterfaceTraceabilityTree.TREEVIEW_EDIT_COMMENT_GUINAME);
		String info = (String)this.getInfoData(editGui, TraceabilityTreeItem.NODE_COMMENT);
		
		// Update info object linked to the tree item
		item.updateInfo(info);
		
		// Update the tree item text that is showed in the tree viewer
		item.getItemWidget().setText(info);
	}
	
	/**
	 * Handler for the new item button pressed event or for
	 * the new item menuitem selected event.
	 * Enables the insert mode to add a new tree item.
	 * @param e Event, new item event data.
	 */
	public void on_newItem_pressed(Event e) {
		// Update the status bar to show the INSERT Mode is ON
		StatusBar sBar = (StatusBar)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_STATUSBAR_WIDGET_NAME);
		if (sBar != null)
			sBar.updateStatus(InterfaceTraceabilityTree.TREEVIEW_STATUSBAR_INSERT_TEXT);
		
		// Open the Choose Item Type Dialog to pick up the node type to insert
		this.getChooseItemTypeDialog().open();
	}
	
	/**
	 * Gets the data typed in by the user in the edition panel.
	 * @param jg JavaGlade, JavaGlade instance used in the construction
	 * of the Traceability Tree Viewer GUI.
	 * @param itemType int, item type of the edited item.
	 * @return Object, Info object with the data typed in by the user.
	 */
	private Object getInfoData(Gui editGui, int itemType) {
		Object result = null;
		
		switch (itemType) {
			case TraceabilityTreeItem.NODE_PRODUCT:
				result = new ProductInfo();
				// Get product reference
				Text t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_REFERENCE_ITEMNAME);
				((ProductInfo)result).setReference(t.getText());
				System.out.println("Reference got: " + t.getText());
				// Get product set number
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_SETNUMBER_ITEMNAME);
				((ProductInfo)result).setSetNumber(t.getText());
				System.out.println("Set Number got: " + t.getText());
				// Get product barcode
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_BARCODE_ENTRY_ITEMNAME);
				((ProductInfo)result).setBarcode(t.getText());
				System.out.println("Barcode got: " + t.getText());
				// Get product description
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_DESCRIPTION_ITEMNAME);
				((ProductInfo)result).setDescription(t.getText());
				System.out.println("Description got: " + t.getText());
				// Get product in date
				DateTime dt = new DateTime();
				dt.setDateFormat(InterfaceTraceabilityTree.CONST_SHORT_DATE_PATTERN);
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_IN_DAY_ITEMNAME);
				String date = t.getText() + "/";
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_IN_MONTH_ITEMNAME);
				date += t.getText() + "/";
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_IN_YEAR_ITEMNAME);
				date += t.getText();
				dt.setDate(date);
				((ProductInfo)result).setDateIn(dt.getDateAsString());
				System.out.println("In Date got: " + dt.getDateAsString());
				// Get product expiry date
				dt = new DateTime();
				dt.setDateFormat(InterfaceTraceabilityTree.CONST_SHORT_DATE_PATTERN);
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_EXPIRY_DAY_ITEMNAME);
				date = t.getText() + "/";
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_EXPIRY_MONTH_ITEMNAME);
				date += t.getText() + "/";
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_EXPIRY_YEAR_ITEMNAME);
				date += t.getText();
				dt.setDate(date);
				((ProductInfo)result).setDateExpiry(dt.getDateAsString());
				System.out.println("Expiry Date got: " + dt.getDateAsString());
				// Get product traceability file
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_TRFILE_ITEMNAME);
				((ProductInfo)result).setTraceabilityFile(t.getText());
				System.out.println("Traceability Filename got: " + t.getText());
				break;
			case TraceabilityTreeItem.NODE_PROCESS:
				result = new ProcessInfo();
				// Get process code
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROCESS_CODE_ITEMNAME);
				((ProcessInfo)result).setCodOperation(t.getText());
				// Get process date
				dt = new DateTime();
				dt.setDateFormat(InterfaceTraceabilityTree.CONST_SHORT_DATE_PATTERN);
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROCESS_DAY_ITEMNAME);
				date = t.getText() + "/";
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROCESS_MONTH_ITEMNAME);
				date += t.getText() + "/";
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROCESS_YEAR_ITEMNAME);
				date += t.getText();
				dt.setDate(date);
				((ProcessInfo)result).setDateProcess(dt.getDateAsString());
				break;
			case TraceabilityTreeItem.NODE_PURCHASE:
				result = new PurchaseInfo();
				// Get purchase code
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PURCHASE_CODE_ITEMNAME);
				((PurchaseInfo)result).setCodPurchaseConfirmation(t.getText());
				// Get purchase supplier
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PURCHASE_SUPPLIER_ITEMNAME);
				((PurchaseInfo)result).setCodSupplier(t.getText());
				break;
			case TraceabilityTreeItem.NODE_PROPERTY:
				// Get property code
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROPERTY_CODE_ITEMNAME);
				String code = t.getText();
				// Get property description
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROPERTY_DESCRIPTION_ITEMNAME);
				String desc = t.getText();
				// Get property type
				Combo c = (Combo)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROPERTY_TYPE_ITEMNAME);
				String type = "" + c.getSelectionIndex();
				// Get property value
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROPERTY_VALUE_ITEMNAME);
				String val = t.getText();
				// Get property pattern
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROPERTY_PATTERN_ITEMNAME);
				String pattern = t.getText();
				result = new PropertyInfo(code, val, type, desc, pattern);
				break;
			case TraceabilityTreeItem.NODE_WAREHOUSE:
				result = new WarehouseInfo();
				// Get warehouse code
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_WAREHOUSE_CODE_ITEMNAME);
				((WarehouseInfo)result).setCodWarehouse(t.getText());
				// Get warehouse description
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_WAREHOUSE_DESCRIPTION_ITEMNAME);
				((WarehouseInfo)result).setDescription(t.getText());
				break;
			case TraceabilityTreeItem.NODE_APPCC:
//				result = new AppccInfo();
				break;
			case TraceabilityTreeItem.NODE_WORKER:
				result = new WorkerInfo();
				// Get worker code
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_WORKER_CODE_ITEMNAME);
				((WorkerInfo)result).setCodWorker(t.getText());
				// Get worker name
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_WORKER_NAME_ITEMNAME);
				((WorkerInfo)result).setDescription(t.getText());
				break;
			case TraceabilityTreeItem.NODE_WORKCENTER:
				result = new WorkcenterInfo();
				// Get workcenter code
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_WORKCENTER_CODE_ITEMNAME);
				((WorkcenterInfo)result).setCodWorkcenter(t.getText());
				// Get workcenter description
				t = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_WORKCENTER_DESCRIPTION_ITEMNAME);
				((WorkcenterInfo)result).setDescription(t.getText());
				break;
			case TraceabilityTreeItem.NODE_COMMENT:
				// Get comment text
				StyledText st = (StyledText)editGui.getWidget(InterfaceTraceabilityTree.EDIT_COMMENT_ITEMNAME);
				result = st.getText();
				break;
			case TraceabilityTreeItem.NODE_UNDEFINED:
				break;
		}
		
		return result;
	}
	
	/**
	 * Builds a new tree item. Insert it at the right index and show it
	 * on the screen. It's used when the inserted item is not the root
	 * item of the tree, i.e. it is not the parent product of the 
	 * traceability tree.  
	 * @param parent TraceabilityTreeItem, parent item of the inserted item.
	 * @param type int, item type of the inserted item.
	 * @param info Object, Info object with the data of the inserted item.
	 */
	private void buildNewTreeItem(TraceabilityTreeItem parent, int type, Object info) {
		LoggerFactory.getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY).
			debug(String.format(InterfaceTraceabilityTree.TREEVIEW_LOG_TREEITEM_CHILDREN, parent.getItemWidget().getItemCount(), parent.getItemWidget().getItems()));
		
		int index = this.getNextIndex(type, parent);
		LoggerFactory.getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY).
			info(String.format(InterfaceTraceabilityTree.TREEVIEW_LOG_TREEITEM_INSERT, type, index));
		
		TraceabilityTreeItem item = null;
		switch (type) {
			// if selected node == PRODUCT
			case TraceabilityTreeItem.NODE_PRODUCT:
				item = this.buildProductItem(parent, (ProductInfo)info, index);
				if (parent != null && parent.getType() == TraceabilityTreeItem.NODE_PROCESS) {
					((ProcessInfo)parent.getInfo()).addIn((ProductInfo)info);	
				}
				break;
			// if selected node == PURCHASE
			case TraceabilityTreeItem.NODE_PURCHASE:
				item = this.buildPurchaseItem(parent, (PurchaseInfo)info, index);
				((ProductInfo)parent.getInfo()).setSource((PurchaseInfo)info);
				break;
			// if selected node == PROPERTY
			case TraceabilityTreeItem.NODE_PROPERTY:
				item = this.buildPropertyItem(parent, (PropertyInfo)info, index);
				((ProductInfo)parent.getInfo()).addProperty((PropertyInfo)info);
				break;
			// if selected node == WAREHOUSE
			case TraceabilityTreeItem.NODE_WAREHOUSE:
				item = this.buildWarehouseItem(parent, (WarehouseInfo)info, index);
				((ProductInfo)parent.getInfo()).addWarehouse((WarehouseInfo)info);
				break;
			// if selected node == COMMENT
			case TraceabilityTreeItem.NODE_COMMENT:
				item = this.buildCommentItem(parent, (String)info, index);
				if (parent.getType() == TraceabilityTreeItem.NODE_PRODUCT)
					((ProductInfo)parent.getInfo()).addComment((String)info);
				else if (parent.getType() == TraceabilityTreeItem.NODE_PROCESS)
					((ProcessInfo)parent.getInfo()).addComment((String)info);
				break;
			// if selected node == PROCESS
			case TraceabilityTreeItem.NODE_PROCESS:
				item = this.buildProcessItem(parent, (ProcessInfo)info, index);
				((ProductInfo)parent.getInfo()).setSource((ProcessInfo)info);
				break;
			// if selected node == WORKER
			case TraceabilityTreeItem.NODE_WORKER:
				item = this.buildWorkerItem(parent, (WorkerInfo)info, index);
				((ProcessInfo)parent.getInfo()).addWorker((WorkerInfo)info);
				break;
			// if selected node == WORKCENTER
			case TraceabilityTreeItem.NODE_WORKCENTER:
				item = this.buildWorkcenterItem(parent, (WorkcenterInfo)info, index);
				((ProcessInfo)parent.getInfo()).addWorkcenter((WorkcenterInfo)info);
				break;
			// if selected node == APPCC
			case TraceabilityTreeItem.NODE_APPCC:
				break;
			// if selected node == UNDEFINED
			case TraceabilityTreeItem.NODE_UNDEFINED:
				break;
		} // switch
		
		if (item != null)
			this.selectItem(item);
	}

	/**
	 * Builds a new tree item. Insert it at the right index and show it
	 * on the screen. It's used when the inserted item is the root
	 * item of the tree, i.e. it is the parent product of the 
	 * traceability tree.  
	 * @param parent Tree, tree widget managed by the Traceability Tree
	 * Viewer. It will be the parent widget of the inserted item.
	 * @param type int, item type of the inserted item.
	 * @param info Object, Info object with the data of the inserted item.
	 */
	private void buildNewTreeItem(Tree parent, int type, Object info) {
		LoggerFactory.getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY).
			debug(String.format(InterfaceTraceabilityTree.TREEVIEW_LOG_TREEITEM_CHILDREN, parent.getItemCount(), parent.getItems()));
		// The parent is the tree widget so the only node that can be the root
		// of a traceability tree is a product node. Otherwise throw error
		if (type == TraceabilityTreeItem.NODE_PRODUCT) {
			TraceabilityTreeItem item = this.buildProductItem(parent, (ProductInfo)info);
			this.selectItem(item);
		}
		else {
			// TO_DO: Throw error message
		}
	}
	
	/**
	 * Return the list of Property Type allowed values.
	 * @return String[], list of Property types.
	 */
	private String[] getPropertyTypeCollection() {
		return new String[] {
				PropertyInfo.CONST_PROPERTY_TYPE_NONE,
				PropertyInfo.CONST_PROPERTY_TYPE_NUMBER,
				PropertyInfo.CONST_PROPERTY_TYPE_STRING,
				PropertyInfo.CONST_PROPERTY_TYPE_DATE,
				PropertyInfo.CONST_PROPERTY_TYPE_BOOLEAN,
				PropertyInfo.CONST_PROPERTY_TYPE_OBJECT
		};
	}
	
	/**
	 * Handler for the closing of the choose item type dialog event. 
	 * Gets the type of item selected by the user as the result.
	 * @param e Event, close choose item type dialog event data.
	 */
	public void on_dialogChooseNodeType_close(Event e) {
		Composite rootComposite = null;
		Widget w = null;

		SwtDialog chooseItemTypeDialog = this.getChooseItemTypeDialog();
		
		Widget okButton = this.gui.getChild("treeViewer_selectTreeItemType").
				getWidget(InterfaceTraceabilityTree.CHOOSE_ITEM_TYPE_OKBUTTON_NAME);
		
		if (!e.widget.equals(okButton)) {
			this.setInsertType(TraceabilityTreeItem.NODE_UNDEFINED);
			this.setInsertMode(false);
			
			// Get the selected tree item
			TraceabilityTreeItem itemSelected = this.getSelectedTreeItem();
			
			// Show the selected tree item
			if (itemSelected == null) {
			} // if no item has been selected}
			else {
				this.showSelectedItem(itemSelected);
			} // else an item has been selected 
			
			// Update the status bar to show the default mode
			StatusBar sBar = (StatusBar)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_STATUSBAR_WIDGET_NAME);
			if (sBar != null)
				sBar.updateStatus(InterfaceTraceabilityTree.TREEVIEW_STATUSBAR_DEFAULT_TEXT);
		}
		else {
			// Get the root composite where the edition panels are embedded
			rootComposite = (Composite)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PANEL_NAME);
			
			int chosenType = 0;
			Gui chooseItemTypeGui = this.gui.getChild("treeViewer_selectTreeItemType");
			Button rb = (Button)chooseItemTypeGui.getWidget(InterfaceTraceabilityTree.CHOOSE_ITEM_TYPE_PRODUCT_RADIOBUTTON_NAME);
			if (rb.getSelection()) {
				chosenType = TraceabilityTreeItem.NODE_PRODUCT;
				this.showProduct(null);
				w = this.getEditProductGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PRODUCT_PANEL_NAME);
			}
			
			rb = (Button)chooseItemTypeGui.getWidget(InterfaceTraceabilityTree.CHOOSE_ITEM_TYPE_PURCHASE_RADIOBUTTON_NAME);
			if (rb.getSelection()) {
				chosenType = TraceabilityTreeItem.NODE_PURCHASE;
				this.showPurchase(null);
				w = this.getEditPurchaseGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PURCHASE_PANEL_NAME);
			}
			
			rb = (Button)chooseItemTypeGui.getWidget(InterfaceTraceabilityTree.CHOOSE_ITEM_TYPE_PROPERTY_RADIOBUTTON_NAME);
			if (rb.getSelection()) {
				chosenType = TraceabilityTreeItem.NODE_PROPERTY;
				this.showProperty(null);
				w = this.getEditPropertyGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PROPERTY_PANEL_NAME);
			}

			rb = (Button)chooseItemTypeGui.getWidget(InterfaceTraceabilityTree.CHOOSE_ITEM_TYPE_WAREHOUSE_RADIOBUTTON_NAME);
			if (rb.getSelection()) {
				chosenType = TraceabilityTreeItem.NODE_WAREHOUSE;
				this.showWarehouse(null);
				w = this.getEditWarehouseGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_WAREHOUSE_PANEL_NAME);
			}

			rb = (Button)chooseItemTypeGui.getWidget(InterfaceTraceabilityTree.CHOOSE_ITEM_TYPE_APPCC_RADIOBUTTON_NAME);
			if (rb.getSelection()) {
				chosenType = TraceabilityTreeItem.NODE_APPCC;
//				this.showAppcc(null);
				w = this.getEditAppccGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_APPCC_PANEL_NAME);
			}

			rb = (Button)chooseItemTypeGui.getWidget(InterfaceTraceabilityTree.CHOOSE_ITEM_TYPE_COMMENT_RADIOBUTTON_NAME);
			if (rb.getSelection()) {
				chosenType = TraceabilityTreeItem.NODE_COMMENT;
				this.showComment(null);
				w = this.getEditCommentGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_COMMENT_PANEL_NAME);
			}

			rb = (Button)chooseItemTypeGui.getWidget(InterfaceTraceabilityTree.CHOOSE_ITEM_TYPE_PROCESS_RADIOBUTTON_NAME);
			if (rb.getSelection()) {
				chosenType = TraceabilityTreeItem.NODE_PROCESS;
				this.showProcess(null);
				w = this.getEditProcessGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PROCESS_PANEL_NAME);
			}

			rb = (Button)chooseItemTypeGui.getWidget(InterfaceTraceabilityTree.CHOOSE_ITEM_TYPE_WORKER_RADIOBUTTON_NAME);
			if (rb.getSelection()) {
				chosenType = TraceabilityTreeItem.NODE_WORKER;
				this.showWorker(null);
				w = this.getEditWorkerGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_WORKER_PANEL_NAME);
			}

			rb = (Button)chooseItemTypeGui.getWidget(InterfaceTraceabilityTree.CHOOSE_ITEM_TYPE_WORKCENTER_RADIOBUTTON_NAME);
			if (rb.getSelection()) {
				chosenType = TraceabilityTreeItem.NODE_WORKCENTER;
				this.showWorkcenter(null);
				w = this.getEditWorkcenterGui().getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_WORKCENTER_PANEL_NAME);
			}
			
			this.setInsertType(chosenType);
			this.setInsertMode(true);
			
			if (w != null && rootComposite != null) {
				((StackLayout)rootComposite.getLayout()).topControl = (Control)w;
				rootComposite.layout(true, true);
			}
		}

		e.doit = false;
		chooseItemTypeDialog.close();
	}
	
	/**
	 * Gets the next index to locate a new tree item.
	 * @param itemType int, type of the new item.
	 * @param parent TraceabilityTreeItem, parent item.
	 * @return int, index at which the new item will be inserted.
	 */
	private int getNextIndex(int itemType, TraceabilityTreeItem parent) {
		int index = -1;
		
		Object info = null;
		if (parent != null)
			info = parent.getInfo();
		
		switch (itemType) {
			// If the item is of type product
			case TraceabilityTreeItem.NODE_PRODUCT:
				if (info instanceof ProcessInfo) {
					index = ((ProcessInfo)info).getLIn()!=null?((ProcessInfo)info).getLIn().size():0;
				}
				break;				
			// if the item is of type purchase
			case TraceabilityTreeItem.NODE_PURCHASE:
			// If the item is of type process
			case TraceabilityTreeItem.NODE_PROCESS:
				if (info instanceof ProductInfo) {
					// Purchase/Process info comes after fixed part of the 
					// product info and the list of the properties of the product.
					index = InterfaceTraceabilityTree.TREEVIEW_START_PRODUCT_PROPERTIES_INDEX;
					index += ((ProductInfo)info).getLProperties()!=null?((ProductInfo)info).getLProperties().size():0;
				}
				break;
			// If the item is of type property
			case TraceabilityTreeItem.NODE_PROPERTY:
				if (info instanceof ProductInfo) {
					// Properties info comes after fixed part of the product info and the
					// other properties of the product.					
					index = InterfaceTraceabilityTree.TREEVIEW_START_PRODUCT_PROPERTIES_INDEX;
					index += ((ProductInfo)info).getLProperties()!=null?((ProductInfo)info).getLProperties().size():0; 
				}
				break;
			// If the item is of type warehouse
			case TraceabilityTreeItem.NODE_WAREHOUSE:
				if (info instanceof ProductInfo) {
					// Warehouse info comes after fixed part of the product info,
					// the list of the properties of the product, the source 
					// (process or purchase) information and the other warehouses.
					index = InterfaceTraceabilityTree.TREEVIEW_START_PRODUCT_PROPERTIES_INDEX;
					index += ((ProductInfo)info).getLProperties()!=null?((ProductInfo)info).getLProperties().size():0;
					index++;
					index += ((ProductInfo)info).getLWarehouses()!=null?((ProductInfo)info).getLWarehouses().size():0;
				}
				break;
			// If the item is of type comment
			case TraceabilityTreeItem.NODE_COMMENT:
				if (info instanceof ProductInfo) {
					// Comment info comes after fixed part of the product info,
					// the list of the properties of the product, the source 
					// (process or purchase) information, the list of warehouses
					// and the other comments.
					index = InterfaceTraceabilityTree.TREEVIEW_START_PRODUCT_PROPERTIES_INDEX;
					index += ((ProductInfo)info).getLProperties()!=null?((ProductInfo)info).getLProperties().size():0;
					index += ((ProductInfo)info).getSourceProcess() != null || ((ProductInfo)info).getSourcePurchase() != null?1:0;
					index += ((ProductInfo)info).getLWarehouses()!=null?((ProductInfo)info).getLWarehouses().size():0;
					index += ((ProductInfo)info).getLComments()!=null?((ProductInfo)info).getLComments().size():0;
				}
				else if (info instanceof ProcessInfo) {
					// Comment info comes after fixed part of the process info,
					// the list of in products involved in the process,
					// the list of the workers that took part in the process, 
					// the workcenter information and the other comments.
					index = InterfaceTraceabilityTree.TREEVIEW_START_PROCESS_PRODUCT_IN_INDEX;
					index += ((ProcessInfo)info).getLIn()!=null?((ProcessInfo)info).getLIn().size():0;
					index += ((ProcessInfo)info).getLWorkers()!=null?((ProcessInfo)info).getLWorkers().size():0;
					index += ((ProcessInfo)info).getLWorkcenters() != null?1:0;
					index += ((ProcessInfo)info).getLComments()!=null?((ProcessInfo)info).getLComments().size():0;
				}
				break;
			// If the item is of type worker
			case TraceabilityTreeItem.NODE_WORKER:
				if (info instanceof ProcessInfo) {
					// Worker info comes after fixed part of the process info and
					// the list of in products involved in the process and the
					// other workers
					index = InterfaceTraceabilityTree.TREEVIEW_START_PROCESS_PRODUCT_IN_INDEX;
					index += ((ProcessInfo)info).getLIn()!=null?((ProcessInfo)info).getLIn().size():0;
					index += ((ProcessInfo)info).getLWorkers()!=null?((ProcessInfo)info).getLWorkers().size():0;
				}
				break;
			// If the item is of type workcenter
			case TraceabilityTreeItem.NODE_WORKCENTER:
				if (info instanceof ProcessInfo) {
					// Workcenter info comes after fixed part of the process info,
					// the list of in products involved in the process,
					// the list of the workers that took part in the process.
					index = InterfaceTraceabilityTree.TREEVIEW_START_PROCESS_PRODUCT_IN_INDEX;
					index += ((ProcessInfo)info).getLIn()!=null?((ProcessInfo)info).getLIn().size():0;
					index += ((ProcessInfo)info).getLWorkers()!=null?((ProcessInfo)info).getLWorkers().size():0;
				}
				break;
			// If the item is of type appcc
			case TraceabilityTreeItem.NODE_APPCC:
				break;
			// If the item is of type undefined
			case TraceabilityTreeItem.NODE_UNDEFINED:
				break;
		}
		
		return index;
	}	
	
	/**
	 * Handler for the Delete button pressed event. 
	 * Deletes the selected tree item.
	 * @param e Event, delete button pressed event data.
	 */
	public void on_delete_pressed(Event e) {
		TraceabilityTreeItem itemSelected = this.getSelectedTreeItem();

		// If the node is of type Product the selected node must be the root node of
		// the product and not any of the child nodes that show properties of the product.
		if (itemSelected != null && itemSelected.getInfo() instanceof ProductInfo) {
			String nodeName = "NODE_PRODUCT_" + ((ProductInfo)itemSelected.getInfo()).getReference();
			if (!itemSelected.getName().equals(nodeName))
				itemSelected = this.itemsByName.get(nodeName);
		}
		// If the node is of type Process the selected node must be the root node of
		// the process and not any of the child nodes that show properties of the process.
		else if (itemSelected != null && itemSelected.getInfo() instanceof ProcessInfo) {
			String nodeName = "NODE_PROCESS_" + ((ProcessInfo)itemSelected.getInfo()).getCodOperation();
			if (!itemSelected.getName().equals(nodeName))
				itemSelected = this.itemsByName.get(nodeName);
		}
		
		this.deleteItem(itemSelected);
		this.showEmpty();
	}

	/**
	 * Deletes a tree item and all its children.
	 * @param item TraceabilityTreeItem, item to be removed.
	 */
	private void deleteItem(TraceabilityTreeItem item) {
		TreeItem itemWidget = null;
		TraceabilityTreeItem parent = null;
		
		// Delete all children items
		if (item != null) {
			itemWidget = item.getItemWidget();
			if (itemWidget.getParentItem() != null)
				parent = this.items.get(itemWidget.getParentItem());
			this.deleteItem(item, parent);
		}
	}
	
	/**
	 * Deletes a tree item and all its children.
	 * @param item TraceabilityTreeItem, item to be removed.
	 * @param parent TraceabilityTreeItem, parent item.
	 */
	private void deleteItem(TraceabilityTreeItem item, TraceabilityTreeItem parent) {
		TreeItem itemWidget = null;
		
		LoggerFactory.getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY).
			info(String.format(InterfaceTraceabilityTree.TREEVIEW_LOG_TREEITEM_DELETE, item.getName()));
		
		// Delete all children items
		if (item != null) {
			itemWidget = item.getItemWidget();
			TreeItem[] lChildren = itemWidget.getItems();
			for (int i=0; lChildren != null && i < lChildren.length; i++) {
				TraceabilityTreeItem childItem = this.items.get(lChildren[i]);
				this.deleteItem(childItem, item);
			} // for each child item
		}

		// If item removed is the root product
		if (parent == null && item.getType() == TraceabilityTreeItem.NODE_PRODUCT) {
		}
		else if (parent != null) {
			switch (item.getType()) {
				// if selected node == PRODUCT
				case TraceabilityTreeItem.NODE_PRODUCT:
					if (parent.getType() == TraceabilityTreeItem.NODE_PROCESS) {
						((ProcessInfo)parent.getInfo()).delIn((ProductInfo)item.getInfo());	
					}
					break;
				// if selected node == PURCHASE
				case TraceabilityTreeItem.NODE_PURCHASE:
					((ProductInfo)parent.getInfo()).setSource((PurchaseInfo)null);
					((ProductInfo)parent.getInfo()).setSourceType(ProductInfo.SOURCE_NONE);
					break;
				// if selected node == PROPERTY
				case TraceabilityTreeItem.NODE_PROPERTY:
					((ProductInfo)parent.getInfo()).delProperty((PropertyInfo)item.getInfo());
					break;
				// if selected node == WAREHOUSE
				case TraceabilityTreeItem.NODE_WAREHOUSE:
					((ProductInfo)parent.getInfo()).delWarehouse((WarehouseInfo)item.getInfo());
					break;
				// if selected node == COMMENT
				case TraceabilityTreeItem.NODE_COMMENT:
					if (parent.getType() == TraceabilityTreeItem.NODE_PRODUCT)
						((ProductInfo)parent.getInfo()).delComment((String)item.getInfo());
					else if (parent.getType() == TraceabilityTreeItem.NODE_PROCESS)
						((ProcessInfo)parent.getInfo()).addComment((String)item.getInfo());
					break;
				// if selected node == PROCESS
				case TraceabilityTreeItem.NODE_PROCESS:
					if (parent.getType() == TraceabilityTreeItem.NODE_PRODUCT) {
						((ProductInfo)parent.getInfo()).setSource((ProcessInfo)null);
						((ProductInfo)parent.getInfo()).setSourceType(ProductInfo.SOURCE_NONE);
					}
					break;
				// if selected node == WORKER
				case TraceabilityTreeItem.NODE_WORKER:
					((ProcessInfo)parent.getInfo()).delWorker((WorkerInfo)item.getInfo());
					break;
				// if selected node == WORKCENTER
				case TraceabilityTreeItem.NODE_WORKCENTER:
					((ProcessInfo)parent.getInfo()).delWorkcenter((WorkcenterInfo)item.getInfo());
					break;
				// if selected node == APPCC
				case TraceabilityTreeItem.NODE_APPCC:
					break;
				// if selected node == UNDEFINED
				case TraceabilityTreeItem.NODE_UNDEFINED:
					break;
			} // switch
		} // else parent != null
		
		// Delete item from the items catalogs
		items.remove(itemWidget);
		itemsByName.remove(item.getName());
		// Dispose the GUI item widget
		itemWidget.dispose();
	}
	
	/**
	 * Handler for the Exit button pressed event. 
	 * Closes the application.
	 * @param e Event, Exit button pressed event data.
	 */
	public void on_exit_pressed(Event e) {
		this.setTraceabilityFilename(null);
		this.gui.getParentWindow().getShell().close();
	}
	
	/**
	 * Handler for the Open button pressed event or for the Open
	 * menuitem selected event. 
	 * Opens a traceability file and builds the traceability tree.
	 * Shows the built tree on screen.
	 * @param e Event, Open event data
	 */
	public void on_open_pressed(Event e) {
		String filename = null;
		
		// Open the Traceability File Chooser Dialog to pick up the traceability file to open
		SwtDialog chooseTrFileDialog = this.getBrowseFileDialog();
		chooseTrFileDialog.getDialog().setText("Open Traceability Filename");
		filename = (String)chooseTrFileDialog.open();
		
		// If Accept or a file has been selected
		if (filename != null && filename.length() > 0 && Validator.getInstance().isValidFile(filename)) {
			this.openTraceabilityFile(filename);
		} // if accept has been pressed
	}
	
	/**
	 * Handler for the New tree button pressed event or for the New Tree
	 * menuitem selection event. 
	 * Clears the opened traceability tree and gets ready for 
	 * starting the construction of a new tree.
	 * @param e Event, New tree event data
	 */
	public void on_newTree_pressed(Event e) {
		// Get the tree widget
		Tree t = (Tree)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_WIDGET_NAME);
		// Enable the tree widget
		t.setEnabled(true);
		
		// Delete the tree contents
		this.deleteTreeContents(t);
		
		// Reset the filename
		this.setTraceabilityFilename(null);
		
		// Show the empty edit panel
		this.showEmpty();
	}
	
	/**
	 * Handler for the Save button pressed event or for the Save 
	 * menuitem selection event. 
	 * Saves the tree content to the opened traceability file.
	 * @param e Event, Save event data.
	 */
	public void on_save_pressed(Event e) {
		// If the opened file is correct
		if (Validator.getInstance().isValidFile(this.traceabilityFilename)) {
			this.saveTraceabilityTree();
		}
		// If the opened file no longer exists or the filename was not correct
		// then user must pick up another new file to save the content to.
		else
			on_saveAs_pressed(e);
	}
	
	/**
	 * Handler for the SaveAs menuitem selection event. 
	 * Selects the file that will hold the tree content, and then 
	 * saves the tree content to the selected file.
	 * @param e Event, SaveAs menuitem selection event data.
	 */
	public void on_saveAs_pressed(Event e) {
		String filename = null;
		
		// Open the Traceability File Chooser Dialog to pick up the traceability file to save the content to
		SwtDialog chooseTrFileDialog = this.getBrowseFileDialog();
		chooseTrFileDialog.getDialog().setText("Save Traceability Filename");
		filename = (String)chooseTrFileDialog.open();
		
		// If Accept or a file has been selected
		if (filename != null && filename.length() > 0) {
			// If the file doesn't exist --> Create it
			if (!Validator.getInstance().isValidFile(filename)) {
				// Create the new file
				try {
					File f = new File(filename);
					f.createNewFile();
				}
				catch (Exception ex) {
					return;
				}
			}
			
			this.setTraceabilityFilename(filename);
			this.saveTraceabilityTree();
		} // if accept has been pressed
	}
	
	/**
	 * Saves the traceability tree content onto an output
	 * stream.
	 * @param out ByteArrayOutputStream out, output stream to
	 * save the traceability tree contents to.
	 */
	public void saveTraceabilityTree(ByteArrayOutputStream out) {
		if (out != null) {
			PrintWriter pw = new PrintWriter(out);
			// Get the tree widget
			Tree t = (Tree)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_WIDGET_NAME);
			
			// Get all the root items (tree items hang directly of the tree widget)
			TreeItem[] lItems = t.getItems();
	
			try {
				// Write the xml header
				pw.write(InterfaceTraceabilityTree.XML_HEADER);
				pw.write(InterfaceTraceabilityTree.END_LINE);

				// Write starting traceability tree tag
				pw.write(InterfaceTraceabilityTree.START_XML_TAG);
				pw.write(InterfaceTraceabilityTree.TRACEABILITY_TREE_TAG);
				pw.write(InterfaceTraceabilityTree.END_XML_TAG);
				pw.write(InterfaceTraceabilityTree.END_LINE);

				pw.flush();
				
				for (int i=0; lItems != null && i < lItems.length; i++) {
					pw.write(this.items.get(lItems[i]).toXml(InterfaceTraceabilityTree.TAB));
					pw.write(InterfaceTraceabilityTree.END_LINE);
					pw.flush();
				} // for each root tree item

				// Write ending traceability tree tag
				pw.write(InterfaceTraceabilityTree.START_XML_TAG);
				pw.write(InterfaceTraceabilityTree.SLASH);
				pw.write(InterfaceTraceabilityTree.TRACEABILITY_TREE_TAG);
				pw.write(InterfaceTraceabilityTree.END_XML_TAG);
				
				pw.close();
			}
			catch (Exception ex) {
				ex.printStackTrace();
				return;
			}
		} // if outStream is not empty
	}
	
	/**
	 * Saves the traceability tree content onto the opened 
	 * traceability file.
	 */
	private void saveTraceabilityTree() {
		FileWriter out = null;
		// Open the file
		try {
			File f = new File(this.getTraceabilityFilename());
			if (!f.exists())
				return;
			
			out = new FileWriter(f);
		}
		catch (Exception ex) {
			ex.printStackTrace();
			out = null;
		}
		
		if (out != null) {
			// Get the tree widget
			Tree t = (Tree)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_WIDGET_NAME);
			
			// Get all the root items (tree items hang directly of the tree widget)
			TreeItem[] lItems = t.getItems();
	
			try {
				// Write the xml header
				out.write(InterfaceTraceabilityTree.XML_HEADER);
				out.write(InterfaceTraceabilityTree.END_LINE);

				// Write starting traceability tree tag
				out.write(InterfaceTraceabilityTree.START_XML_TAG);
				out.write(InterfaceTraceabilityTree.TRACEABILITY_TREE_TAG);
				out.write(InterfaceTraceabilityTree.END_XML_TAG);
				out.write(InterfaceTraceabilityTree.END_LINE);

				out.flush();
				
				for (int i=0; lItems != null && i < lItems.length; i++) {
					out.write(this.items.get(lItems[i]).toXml(InterfaceTraceabilityTree.TAB));
					out.write(InterfaceTraceabilityTree.END_LINE);
					out.flush();
				} // for each root tree item

				// Write ending traceability tree tag
				out.write(InterfaceTraceabilityTree.START_XML_TAG);
				out.write(InterfaceTraceabilityTree.SLASH);
				out.write(InterfaceTraceabilityTree.TRACEABILITY_TREE_TAG);
				out.write(InterfaceTraceabilityTree.END_XML_TAG);
				
				out.close();
			}
			catch (Exception ex) {
				ex.printStackTrace();
				return;
			}
		} // if outFile was opened
	}
	
	/**
	 * Handler for the barcode enty changed event.
	 * Updates the Product barcode's image item.
	 * @param e Event, barcode entry changed event data.
	 */
	public void on_entryProductBarcode_changed(Event e) {
		Tree t = (Tree)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_WIDGET_NAME);
		
		TraceabilityTreeItem itemSelected = this.getSelectedTreeItem(t);
		
		Gui editGui = this.getEditProductGui();

		// If the selected item is of Product type
		if (itemSelected == null || itemSelected.getInfo() instanceof ProductInfo) {
			ProductInfo info = (ProductInfo)this.getInfoData(editGui, TraceabilityTreeItem.NODE_PRODUCT);
			Label l = (Label)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_BARCODE_IMAGE_ITEMNAME);
			Image img = null;
			// Generate the barcode image
			if (info.getBarcode() != null && info.getBarcode().length() > 0) {
				img = BarcodeGenerator.createBarcodeImage(info.getBarcode(), ExplicaGUIBuilder.getInstance().getDisplay());
			}
			// Update the widget with the new barcode image
			l.setImage(img);
			
			// Refresh the screen
			Composite rootComposite = (Composite)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PANEL_NAME);
			rootComposite.layout(true, true);
			
			System.out.println("Generado codigo de barras: " + info.getBarcode());
		}
	}
	
	/**
	 * Handler for the choose traceability file button pressed event. 
	 * Opens a traceability file and appends the traceability tree to the
	 * process node selected.
	 * @param e Event, Open event data
	 */
	public void on_buttonProductTraceabilityFile_pressed(Event e) {
		String filename = null;
		
		// Open the Traceability File Chooser Dialog to pick up the traceability file to open
		SwtDialog chooseTrFileDialog = this.getBrowseFileDialog();
		filename = (String)chooseTrFileDialog.open();
		
		// If Accept or a file has been selected
		if (filename != null && filename.length() > 0 && Validator.getInstance().isValidFile(filename)) {
			TraceabilityTree trTree = null;
			
			// Parse the selected traceability file
			try {
				TraceabilityTreeParser parser = new TraceabilityTreeParser(filename);
				trTree = parser.getTrTree();
			}
			catch (Exception tEx) {
				tEx.printStackTrace();
				trTree = null;
			}
			
			// Update the edit panel with the info of the root product
			// of the selected traceability file
			if (trTree != null) {
				ProductInfo prodInfo = trTree.getProduct();
				prodInfo.setTraceabilityFile(filename);
				this.showProduct(prodInfo);
			}
		} // if accept has been pressed
	}
	
	/**
	 * Handler for the choose in date button pressed event. 
	 * Shows the calendar to pick up an in date for the product and
	 * updates the edit panel with the selected date.
	 * @param e Event, Button pressed event data
	 */
	public void on_buttonProductDateIn_pressed(Event e) {
		Gui editGui = this.getEditProductGui();
		// Register the destiny widgets that will be updated after the date is chosen
		this.dayWidget = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_IN_DAY_ITEMNAME);
		this.monthWidget = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_IN_MONTH_ITEMNAME);
		this.yearWidget = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_IN_YEAR_ITEMNAME);
		
		// Open the Date Chooser Dialog to pick up the date
		this.getChooseDateDialog().open();
	}
	
	/**
	 * Handler for the choose expiry date button pressed event. 
	 * Shows the calendar to pick up an expiry date for the product and
	 * updates the edit panel with the selected date.
	 * @param e Event, Button pressed event data
	 */
	public void on_buttonProductDateExpiry_pressed(Event e) {
		Gui editGui = this.getEditProductGui();
		// Register the destiny widgets that will be updated after the date is chosen
		this.dayWidget = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_EXPIRY_DAY_ITEMNAME);
		this.monthWidget = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_EXPIRY_MONTH_ITEMNAME);
		this.yearWidget = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PRODUCT_EXPIRY_YEAR_ITEMNAME);
		
		// Open the Date Chooser Dialog to pick up the date
		this.getChooseDateDialog().open();
	}
	
	/**
	 * Handler for the choose process date button pressed event. 
	 * Shows the calendar to pick up a process date for the process and
	 * updates the edit panel with the selected date.
	 * @param e Event, Button pressed event data
	 */
	public void on_buttonProcessDate_pressed(Event e) {
		Gui editGui = this.getEditProcessGui();
		// Register the destiny widgets that will be updated after the date is chosen
		this.dayWidget = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROCESS_DAY_ITEMNAME);
		this.monthWidget = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROCESS_MONTH_ITEMNAME);
		this.yearWidget = (Text)editGui.getWidget(InterfaceTraceabilityTree.EDIT_PROCESS_YEAR_ITEMNAME);
		
		// Open the Date Chooser Dialog to pick up the date
		this.getChooseDateDialog().open();
	}
	
	/**
	 * Handler for the closing of the choose date dialog event. 
	 * Gets the date selected by the user as the result.
	 * @param e Event, close choose date dialog event data.
	 */
	public void on_dialogChooseDate_close(Event e) {
		SwtDialog chooseDateDialog = this.getChooseDateDialog();
		Gui chooseDateGui = this.gui.getChild("treeViewer_selectDate");
		
		Widget okButton = chooseDateGui.getWidget(InterfaceTraceabilityTree.CHOOSE_DATE_OKBUTTON_NAME);
		
		if (e.widget.equals(okButton)) {
			// Get the calendar widget from the choose date dialog
			org.eclipse.swt.widgets.DateTime dt = (org.eclipse.swt.widgets.DateTime)chooseDateGui.getWidget(InterfaceTraceabilityTree.CHOOSE_DATE_CALENDAR_NAME);
			if (this.dayWidget != null)
				this.dayWidget.setText("" + dt.getDay());
			if (this.monthWidget != null)
				this.monthWidget.setText("" + (dt.getMonth()+1));
			if (this.yearWidget != null)
				this.yearWidget.setText("" + dt.getYear());
		}

		// Refresh the screen
		Composite rootComposite = (Composite)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PANEL_NAME);
		rootComposite.layout(true, true);
		
		// Hide the choose date dialog
		e.doit = false;
		chooseDateDialog.close();
	}
	
	/**
	 * Handler for the closing of the show result messages dialog event. 
	 * Hides the result message dialog.
	 * @param e Event, close result message dialog event data.
	 */
	public void on_dialogResultMessage_close(Event e) {
		SwtDialog resultMessageDialog = this.getShowMessageDialog();
		
		// Clear the text of the resultmessage dialog
		StyledText text = (StyledText)this.gui.getChild("treeViewer_message").getWidget(InterfaceTraceabilityTree.RESULT_MESSAGE_TEXT_NAME);
		text.setText("");
		
		// Hide the result message dialog
		e.doit = false;
		resultMessageDialog.close();
	}
	
	/**
	 * Show to the user a dialog with all the result messages.
	 * @param editGui Gui, Gui instance resulted from the edit GUI construction process. 
	 * @param lResultMessages ArrayList<ResultMessage>, list of result messages to show.
	 */
	private void showResultMessages(Gui editGui, ArrayList<ResultMessage> lResultMessages) {
		// Get the result message text widget
		StyledText text = (StyledText)this.gui.getChild("treeViewer_message").getWidget(InterfaceTraceabilityTree.RESULT_MESSAGE_TEXT_NAME);
		
		// Format the aspect of the Result Message text widget
		text.setWordWrap(false);

		// Stores the number of the last inserted line
		int lastLine = 0;
		
		// Build the list bullet applied to each result message
		StyleRange style0 = new StyleRange();
	    style0.metrics = new GlyphMetrics(0, 0, 40);
	    style0.foreground = ExplicaGUIBuilder.getInstance().getColor(SWT.COLOR_RED);
	    Bullet bullet0 = new Bullet(style0);
		
		// Build the result message text with all the result messages got
		// as the result of the operation. The different messages will be showed
		// formatted as a list.
		for (int i=0; lResultMessages != null && i<lResultMessages.size(); i++) {
			ResultMessage resMsg = lResultMessages.get(i);
			// Add result message text to the text widget
			text.setText(text.getText() + (lastLine > 0? "\n":"") + resMsg.toString());
			// Add the bullet of the result message
			text.setLineBullet(lastLine, text.getLineCount() - lastLine, bullet0);
			lastLine = text.getLineCount();
			
			// Change to red the background colour of the widget
			if (resMsg.getFieldName() != null) {
				StringTokenizer tok = new StringTokenizer(resMsg.getFieldName(), "|");
				while (tok != null && tok.hasMoreTokens()) {
					Widget w = editGui.getWidget(tok.nextToken());
					((Control)w).setBackground(ExplicaGUIBuilder.getInstance().getColor(SWT.COLOR_RED));
				} // while there are more field names
			} // if resMsg.fieldName is not null
		}
		
		LoggerFactory.getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY).
			info(String.format(InterfaceTraceabilityTree.TREEVIEW_LOG_SHOWMESSAGE, text.getText()));
	
		text.setWordWrap(true);
		
		// Show the error dialog with the error messages
		this.getShowMessageDialog().open();
	}
	
	/**
	 * Handler for the result message text modify event.
	 * Updates the scroll bars needed to see the result messages on screen.
	 * @param e Event, result message text modify event data.
	 */
	public void on_resultMessageText_modify(Event e) {
		StyledText text = (StyledText)e.widget;
		Composite content = text.getParent(); 
		LoggerFactory.getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY).
			debug(String.format(InterfaceTraceabilityTree.TREEVIEW_LOG_SHOWMESSAGE_MODIFIED, text.getText()));
		
		ScrolledComposite scroll = (ScrolledComposite)content.getParent();
		scroll.setExpandHorizontal(true);
		scroll.setExpandVertical(true);

		content.setSize(text.computeSize(SWT.DEFAULT, SWT.DEFAULT));
		scroll.setMinSize(content.computeSize(SWT.DEFAULT, SWT.DEFAULT));
	}

	/**
	 * Logs the list of widgets built for the traceability tree viewer module.
	 * @param widgets Hashtable, hashtable with all the widgets built.
	 */
	private void logWidgetList(Hashtable widgets) {
		StringBuffer logWidgetsBuffer = new StringBuffer();
		logWidgetsBuffer.append(InterfaceTraceabilityTree.TREEVIEW_LOG_WIDGETLIST);
		logWidgetsBuffer.append("\n");
		Iterator it = widgets.keySet().iterator();
		while (it.hasNext()) {
			Object key = it.next(); 
			logWidgetsBuffer.append(key);
			logWidgetsBuffer.append("\n");			
			logWidgetsBuffer.append(InterfaceTraceabilityTree.TREEVIEW_LOG_WIDGETSEPARATOR);
			logWidgetsBuffer.append("\n");
		} // while there are more widgets
		
		LoggerFactory.getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY).
			debug(logWidgetsBuffer.toString());
	}
	
	public void on_editPanel_resized(Event e) {
		ClientContext.getInstance().getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY).info("Resizing TreeView edit panel...");
		System.out.println("Resizing....... ");
		Composite editPanel = (Composite)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_EDIT_PANEL_NAME);
		System.out.println("Resizing....... EDIT PANEL = " + editPanel);		
		ScrolledComposite scroll = (ScrolledComposite)editPanel.getParent().getParent();
		System.out.println("Resizing....... SCROLL = " + scroll);
		editPanel.pack(true);
		scroll.setMinSize(editPanel.computeSize(SWT.DEFAULT, SWT.DEFAULT));
		System.out.println("Resizing....... " + editPanel.computeSize(SWT.DEFAULT, SWT.DEFAULT));
		ClientContext.getInstance().getLogger(InterfaceTraceabilityTree.TREEVIEW_LOG_CATEGORY).info("Resizing TreeView edit panel..." + editPanel.computeSize(SWT.DEFAULT, SWT.DEFAULT));
	}
	
	
	public InputStream getInputStream(String path) {
		return this.getClass().getResourceAsStream(path);
	}

	public URL getCompletePath(String path) {
		return this.getClass().getResource(path);
	}
	
	private SwtDialog getChooseItemTypeDialog() {
		return this.gui.getChild("treeViewer_selectTreeItemType").getDialog(InterfaceTraceabilityTree.CHOOSE_ITEM_TYPE_DIALOG_NAME);
	}
	
	private SwtDialog getChooseDateDialog() {
		return this.gui.getChild("treeViewer_selectDate").getDialog(InterfaceTraceabilityTree.CHOOSE_DATE_DIALOG_NAME);
	}
	
	private SwtDialog getBrowseFileDialog() {
		return this.gui.getChild("treeViewer_selectFile").getDialog(InterfaceTraceabilityTree.CHOOSE_TRACEABILITY_FILE_DIALOG_NAME);
	}
	
	private SwtDialog getShowMessageDialog() {
		return this.gui.getChild("treeViewer_message").getDialog(InterfaceTraceabilityTree.RESULT_MESSAGE_DIALOG_NAME);
	}
	
	private Gui getEditProductGui() {
		return this.gui.getChild(InterfaceTraceabilityTree.TREEVIEW_EDIT_PRODUCT_GUINAME);
	}
	
	private Gui getEditPurchaseGui() {
		return this.gui.getChild(InterfaceTraceabilityTree.TREEVIEW_EDIT_PURCHASE_GUINAME);
	}
	
	private Gui getEditProcessGui() {
		return this.gui.getChild(InterfaceTraceabilityTree.TREEVIEW_EDIT_PROCESS_GUINAME);
	}
	
	private Gui getEditPropertyGui() {
		return this.gui.getChild(InterfaceTraceabilityTree.TREEVIEW_EDIT_PROPERTY_GUINAME);
	}
	
	private Gui getEditCommentGui() {
		return this.gui.getChild(InterfaceTraceabilityTree.TREEVIEW_EDIT_COMMENT_GUINAME);
	}
	
	private Gui getEditWorkerGui() {
		return this.gui.getChild(InterfaceTraceabilityTree.TREEVIEW_EDIT_WORKER_GUINAME);
	}
	
	private Gui getEditWorkcenterGui() {
		return this.gui.getChild(InterfaceTraceabilityTree.TREEVIEW_EDIT_WORKCENTER_GUINAME);
	}
	
	private Gui getEditWarehouseGui() {
		return this.gui.getChild(InterfaceTraceabilityTree.TREEVIEW_EDIT_WAREHOUSE_GUINAME);
	}
	
	private Gui getEditAppccGui() {
		return this.gui.getChild(InterfaceTraceabilityTree.TREEVIEW_EDIT_APPCC_GUINAME);
	}
	
	private void selectItem(TraceabilityTreeItem item) {
		if (item != null && item.getItemWidget() != null) {
			Tree t = (Tree)this.gui.getWidget(InterfaceTraceabilityTree.TREEVIEW_WIDGET_NAME);
			if (t != null)
				t.select(item.getItemWidget());
		}
	}
	
	/**
	 * Returns tag Id assigned to CVS source file.
	 */
	public static String getRevision() {
		return "$Id: TraceabilityTreeView.java,v 1.5 2009-09-28 10:18:46 mario Exp $";
	}
}